1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/containers/extend.h"
6
7 #include <initializer_list>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
11
12 #include "base/containers/span.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base {
17
18 namespace {
19
20 using testing::ElementsAre;
21
22 struct NonCopyable {
23 char c_;
NonCopyablebase::__anon0d5ff9ab0111::NonCopyable24 explicit NonCopyable(char c) : c_(c) {}
25 NonCopyable(NonCopyable&&) = default;
26 NonCopyable& operator=(NonCopyable&& other) = default;
27
28 NonCopyable(const NonCopyable&) = delete;
29 NonCopyable& operator=(const NonCopyable&) = delete;
30 };
31
operator ==(const NonCopyable & a,const NonCopyable & b)32 bool operator==(const NonCopyable& a, const NonCopyable& b) {
33 return a.c_ == b.c_;
34 }
35
36 static_assert(std::is_move_constructible_v<NonCopyable>, "");
37 static_assert(!std::is_copy_constructible_v<NonCopyable>, "");
38
39 struct CopyableMovable {
40 bool copied_;
41 char c_;
CopyableMovablebase::__anon0d5ff9ab0111::CopyableMovable42 explicit CopyableMovable(char c) : copied_(false), c_(c) {}
CopyableMovablebase::__anon0d5ff9ab0111::CopyableMovable43 CopyableMovable(const CopyableMovable& other) : copied_(true), c_(other.c_) {}
44
45 CopyableMovable& operator=(const CopyableMovable&) = default;
46 CopyableMovable(CopyableMovable&&) = default;
47 CopyableMovable& operator=(CopyableMovable&& other) = default;
48 };
49
operator ==(const CopyableMovable & a,const CopyableMovable & b)50 bool operator==(const CopyableMovable& a, const CopyableMovable& b) {
51 return a.c_ == b.c_;
52 }
53
54 } // namespace
55
TEST(ExtendTest,ExtendWithMove)56 TEST(ExtendTest, ExtendWithMove) {
57 std::vector<NonCopyable> dst;
58 for (char c : {'a', 'b', 'c', 'd'})
59 dst.emplace_back(c);
60 std::vector<NonCopyable> src;
61 for (char c : {'e', 'f', 'g'})
62 src.emplace_back(c);
63 std::vector<NonCopyable> expected;
64 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
65 expected.emplace_back(c);
66
67 Extend(dst, std::move(src));
68 EXPECT_EQ(dst, expected);
69 EXPECT_TRUE(src.empty());
70 }
71
TEST(ExtendTest,ExtendCopyableWithMove)72 TEST(ExtendTest, ExtendCopyableWithMove) {
73 std::vector<CopyableMovable> dst;
74 for (char c : {'a', 'b', 'c', 'd'})
75 dst.emplace_back(c);
76 std::vector<CopyableMovable> src;
77 for (char c : {'e', 'f', 'g'})
78 src.emplace_back(c);
79 std::vector<CopyableMovable> expected;
80 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
81 expected.emplace_back(c);
82
83 Extend(dst, std::move(src));
84 EXPECT_EQ(dst, expected);
85 EXPECT_TRUE(src.empty());
86 }
87
TEST(ExtendTest,ExtendWithCopy)88 TEST(ExtendTest, ExtendWithCopy) {
89 std::vector<CopyableMovable> dst;
90 for (char c : {'a', 'b', 'c', 'd'})
91 dst.emplace_back(c);
92 std::vector<CopyableMovable> src;
93 for (char c : {'e', 'f', 'g'})
94 src.emplace_back(c);
95 std::vector<CopyableMovable> expected;
96 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
97 expected.emplace_back(c);
98
99 EXPECT_FALSE(dst[0].copied_);
100 Extend(dst, src);
101 EXPECT_EQ(dst, expected);
102 EXPECT_FALSE(dst[0].copied_);
103 EXPECT_TRUE(dst[dst.size() - 1].copied_);
104 }
105
TEST(ExtendTest,ExtendWithSpan)106 TEST(ExtendTest, ExtendWithSpan) {
107 static constexpr uint8_t kRawArray[] = {3, 4, 5};
108
109 static constexpr auto kVectorGenerator = []() -> std::vector<uint8_t> {
110 return {9, 10, 11};
111 };
112
113 static const std::vector<uint8_t> kConstVector = kVectorGenerator();
114 static std::vector<uint8_t> kMutVector = kVectorGenerator();
115
116 std::vector<uint8_t> dst;
117
118 // Selects overload for span<const uint8_t, 3>.
119 Extend(dst, span(kRawArray));
120 EXPECT_THAT(dst, ElementsAre(3, 4, 5));
121
122 // Selects overload for span<uint8_t, 3>.
123 static std::array<uint8_t, 3> kArray = {6, 7, 8};
124 Extend(dst, span(kArray));
125 EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8));
126
127 // Selects overload for span<const uint8_t, dynamic_extent>.
128 Extend(dst, span(kConstVector));
129 EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8, 9, 10, 11));
130
131 // Selects overload for span<uint8_t, dynamic_extent>.
132 Extend(dst, span(kMutVector));
133 EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 10, 11));
134 }
135
136 } // namespace base
137