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 "testing/gtest/include/gtest/gtest.h"
13
14 namespace base {
15
16 namespace {
17
18 struct NonCopyable {
19 char c_;
NonCopyablebase::__anond6cc66890111::NonCopyable20 explicit NonCopyable(char c) : c_(c) {}
21 NonCopyable(NonCopyable&&) = default;
22 NonCopyable& operator=(NonCopyable&& other) = default;
23
24 NonCopyable(const NonCopyable&) = delete;
25 NonCopyable& operator=(const NonCopyable&) = delete;
26 };
27
operator ==(const NonCopyable & a,const NonCopyable & b)28 bool operator==(const NonCopyable& a, const NonCopyable& b) {
29 return a.c_ == b.c_;
30 }
31
32 static_assert(std::is_move_constructible_v<NonCopyable>, "");
33 static_assert(!std::is_copy_constructible_v<NonCopyable>, "");
34
35 struct CopyableMovable {
36 bool copied_;
37 char c_;
CopyableMovablebase::__anond6cc66890111::CopyableMovable38 explicit CopyableMovable(char c) : copied_(false), c_(c) {}
CopyableMovablebase::__anond6cc66890111::CopyableMovable39 CopyableMovable(const CopyableMovable& other) : copied_(true), c_(other.c_) {}
40
41 CopyableMovable& operator=(const CopyableMovable&) = default;
42 CopyableMovable(CopyableMovable&&) = default;
43 CopyableMovable& operator=(CopyableMovable&& other) = default;
44 };
45
operator ==(const CopyableMovable & a,const CopyableMovable & b)46 bool operator==(const CopyableMovable& a, const CopyableMovable& b) {
47 return a.c_ == b.c_;
48 }
49
50 } // namespace
51
TEST(ExtendTest,ExtendWithMove)52 TEST(ExtendTest, ExtendWithMove) {
53 std::vector<NonCopyable> dst;
54 for (char c : {'a', 'b', 'c', 'd'})
55 dst.emplace_back(c);
56 std::vector<NonCopyable> src;
57 for (char c : {'e', 'f', 'g'})
58 src.emplace_back(c);
59 std::vector<NonCopyable> expected;
60 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
61 expected.emplace_back(c);
62
63 Extend(dst, std::move(src));
64 EXPECT_EQ(dst, expected);
65 EXPECT_TRUE(src.empty());
66 }
67
TEST(ExtendTest,ExtendCopyableWithMove)68 TEST(ExtendTest, ExtendCopyableWithMove) {
69 std::vector<CopyableMovable> dst;
70 for (char c : {'a', 'b', 'c', 'd'})
71 dst.emplace_back(c);
72 std::vector<CopyableMovable> src;
73 for (char c : {'e', 'f', 'g'})
74 src.emplace_back(c);
75 std::vector<CopyableMovable> expected;
76 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
77 expected.emplace_back(c);
78
79 Extend(dst, std::move(src));
80 EXPECT_EQ(dst, expected);
81 EXPECT_TRUE(src.empty());
82 }
83
TEST(ExtendTest,ExtendWithCopy)84 TEST(ExtendTest, ExtendWithCopy) {
85 std::vector<CopyableMovable> dst;
86 for (char c : {'a', 'b', 'c', 'd'})
87 dst.emplace_back(c);
88 std::vector<CopyableMovable> src;
89 for (char c : {'e', 'f', 'g'})
90 src.emplace_back(c);
91 std::vector<CopyableMovable> expected;
92 for (char c : {'a', 'b', 'c', 'd', 'e', 'f', 'g'})
93 expected.emplace_back(c);
94
95 EXPECT_FALSE(dst[0].copied_);
96 Extend(dst, src);
97 EXPECT_EQ(dst, expected);
98 EXPECT_FALSE(dst[0].copied_);
99 EXPECT_TRUE(dst[dst.size() - 1].copied_);
100 }
101
102 } // namespace base
103