• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/adapters.h"
13 #include "base/containers/circular_deque.h"
14 #include "base/containers/span.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 
20 namespace {
21 
22 using testing::ElementsAre;
23 
24 struct NonCopyable {
25   char c_;
NonCopyablebase::__anon373c01710111::NonCopyable26   explicit NonCopyable(char c) : c_(c) {}
27   NonCopyable(NonCopyable&&) = default;
28   NonCopyable& operator=(NonCopyable&& other) = default;
29 
30   NonCopyable(const NonCopyable&) = delete;
31   NonCopyable& operator=(const NonCopyable&) = delete;
32 };
33 
operator ==(const NonCopyable & a,const NonCopyable & b)34 bool operator==(const NonCopyable& a, const NonCopyable& b) {
35   return a.c_ == b.c_;
36 }
37 
38 static_assert(std::is_move_constructible_v<NonCopyable>, "");
39 static_assert(!std::is_copy_constructible_v<NonCopyable>, "");
40 
41 struct CopyableMovable {
42   bool copied_;
43   char c_;
CopyableMovablebase::__anon373c01710111::CopyableMovable44   explicit CopyableMovable(char c) : copied_(false), c_(c) {}
CopyableMovablebase::__anon373c01710111::CopyableMovable45   CopyableMovable(const CopyableMovable& other) : copied_(true), c_(other.c_) {}
46 
47   CopyableMovable& operator=(const CopyableMovable&) = default;
48   CopyableMovable(CopyableMovable&&) = default;
49   CopyableMovable& operator=(CopyableMovable&& other) = default;
50 };
51 
operator ==(const CopyableMovable & a,const CopyableMovable & b)52 bool operator==(const CopyableMovable& a, const CopyableMovable& b) {
53   return a.c_ == b.c_;
54 }
55 
56 }  // namespace
57 
TEST(ExtendTest,ExtendWithMove)58 TEST(ExtendTest, ExtendWithMove) {
59   std::vector<NonCopyable> dst;
60   for (char c : {'a', 'b', 'c', 'd'})
61     dst.emplace_back(c);
62   std::vector<NonCopyable> src;
63   for (char c : {'e', 'f', 'g'})
64     src.emplace_back(c);
65   std::vector<NonCopyable> expected;
66   for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
67     expected.emplace_back(c);
68 
69   Extend(dst, std::move(src));
70   EXPECT_EQ(dst, expected);
71   EXPECT_TRUE(src.empty());
72 }
73 
TEST(ExtendTest,ExtendCopyableWithMove)74 TEST(ExtendTest, ExtendCopyableWithMove) {
75   std::vector<CopyableMovable> dst;
76   for (char c : {'a', 'b', 'c', 'd'})
77     dst.emplace_back(c);
78   std::vector<CopyableMovable> src;
79   for (char c : {'e', 'f', 'g'})
80     src.emplace_back(c);
81   std::vector<CopyableMovable> expected;
82   for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
83     expected.emplace_back(c);
84 
85   Extend(dst, std::move(src));
86   EXPECT_EQ(dst, expected);
87   EXPECT_TRUE(src.empty());
88 }
89 
TEST(ExtendTest,ExtendWithCopy)90 TEST(ExtendTest, ExtendWithCopy) {
91   std::vector<CopyableMovable> dst;
92   for (char c : {'a', 'b', 'c', 'd'})
93     dst.emplace_back(c);
94   std::vector<CopyableMovable> src;
95   for (char c : {'e', 'f', 'g'})
96     src.emplace_back(c);
97   std::vector<CopyableMovable> expected;
98   for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
99     expected.emplace_back(c);
100 
101   EXPECT_FALSE(dst[0].copied_);
102   Extend(dst, src);
103   EXPECT_EQ(dst, expected);
104   EXPECT_FALSE(dst[0].copied_);
105   EXPECT_TRUE(dst[dst.size() - 1].copied_);
106 }
107 
TEST(ExtendTest,ExtendWithSpan)108 TEST(ExtendTest, ExtendWithSpan) {
109   static constexpr uint8_t kRawArray[] = {3, 4, 5};
110 
111   static constexpr auto kVectorGenerator = []() -> std::vector<uint8_t> {
112     return {9, 10, 11};
113   };
114 
115   static const std::vector<uint8_t> kConstVector = kVectorGenerator();
116   static std::vector<uint8_t> kMutVector = kVectorGenerator();
117 
118   std::vector<uint8_t> dst;
119 
120   // Selects overload for span<const uint8_t, 3>.
121   Extend(dst, span(kRawArray));
122   EXPECT_THAT(dst, ElementsAre(3, 4, 5));
123 
124   // Selects overload for span<uint8_t, 3>.
125   static std::array<uint8_t, 3> kArray = {6, 7, 8};
126   Extend(dst, span(kArray));
127   EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8));
128 
129   // Selects overload for span<const uint8_t, dynamic_extent>.
130   Extend(dst, span(kConstVector));
131   EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8, 9, 10, 11));
132 
133   // Selects overload for span<uint8_t, dynamic_extent>.
134   Extend(dst, span(kMutVector));
135   EXPECT_THAT(dst, ElementsAre(3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 10, 11));
136 
137   // Input is convertible to span.
138   Extend(dst, kRawArray);
139   EXPECT_THAT(dst,
140               ElementsAre(3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 10, 11, 3, 4, 5));
141 }
142 
TEST(ExtendTest,ExtendWithRanges)143 TEST(ExtendTest, ExtendWithRanges) {
144   std::set<int> set = {1, 2, 3};
145   circular_deque<int> deque = {4, 5, 6};
146   {
147     std::vector<int> dst;
148     Extend(dst, Reversed(set));
149     EXPECT_THAT(dst, ElementsAre(3, 2, 1));
150     Extend(dst, Reversed(deque));
151     EXPECT_THAT(dst, ElementsAre(3, 2, 1, 6, 5, 4));
152   }
153 
154   {
155     std::vector<int> dst;
156     Extend(dst, set, [](int val) { return -val; });
157     EXPECT_THAT(dst, ElementsAre(-1, -2, -3));
158     Extend(dst, deque, [](int val) { return val + 1; });
159     EXPECT_THAT(dst, ElementsAre(-1, -2, -3, 5, 6, 7));
160   }
161 
162   {
163     std::vector<int> dst;
164     Extend(dst, Reversed(set), [](int val) { return val * val; });
165     EXPECT_THAT(dst, ElementsAre(9, 4, 1));
166     Extend(dst, Reversed(deque), [](int val) { return val - 1; });
167     EXPECT_THAT(dst, ElementsAre(9, 4, 1, 5, 4, 3));
168   }
169 }
170 
171 }  // namespace base
172