|
|
@ -1841,98 +1841,185 @@ MATCHER(HasValue, "") { |
|
|
|
return ::testing::get<0>(arg).value() == ::testing::get<1>(arg); |
|
|
|
return ::testing::get<0>(arg).value() == ::testing::get<1>(arg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TEST(MoveAssignment, NonAssignable) { |
|
|
|
TEST(NonAssignableMoveAssignmentTest, AllocatedToInline) { |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
{ |
|
|
|
InstanceTracker tracker; |
|
|
|
InstanceTracker tracker; |
|
|
|
absl::InlinedVector<X, 2> inlined; |
|
|
|
absl::InlinedVector<X, 2> inlined; |
|
|
|
inlined.emplace_back(1); |
|
|
|
inlined.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> allocated; |
|
|
|
absl::InlinedVector<X, 2> allocated; |
|
|
|
allocated.emplace_back(1); |
|
|
|
allocated.emplace_back(1); |
|
|
|
allocated.emplace_back(2); |
|
|
|
allocated.emplace_back(2); |
|
|
|
allocated.emplace_back(3); |
|
|
|
allocated.emplace_back(3); |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inlined = std::move(allocated); |
|
|
|
inlined = std::move(allocated); |
|
|
|
// passed ownership of the allocated storage
|
|
|
|
// passed ownership of the allocated storage
|
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 3); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 3); |
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
TEST(NonAssignableMoveAssignmentTest, InlineToAllocated) { |
|
|
|
InstanceTracker tracker; |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
absl::InlinedVector<X, 2> inlined; |
|
|
|
InstanceTracker tracker; |
|
|
|
inlined.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> inlined; |
|
|
|
absl::InlinedVector<X, 2> allocated; |
|
|
|
inlined.emplace_back(1); |
|
|
|
allocated.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> allocated; |
|
|
|
allocated.emplace_back(2); |
|
|
|
allocated.emplace_back(1); |
|
|
|
allocated.emplace_back(3); |
|
|
|
allocated.emplace_back(2); |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
allocated.emplace_back(3); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
allocated = std::move(inlined); |
|
|
|
allocated = std::move(inlined); |
|
|
|
// Moved elements
|
|
|
|
// Moved elements
|
|
|
|
EXPECT_EQ(tracker.moves(), 1); |
|
|
|
EXPECT_EQ(tracker.moves(), 1); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 1); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 1); |
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(allocated, Pointwise(HasValue(), {1})); |
|
|
|
EXPECT_THAT(allocated, Pointwise(HasValue(), {1})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
TEST(NonAssignableMoveAssignmentTest, InlineToInline) { |
|
|
|
InstanceTracker tracker; |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
absl::InlinedVector<X, 2> inlined_a; |
|
|
|
InstanceTracker tracker; |
|
|
|
inlined_a.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> inlined_a; |
|
|
|
absl::InlinedVector<X, 2> inlined_b; |
|
|
|
inlined_a.emplace_back(1); |
|
|
|
inlined_b.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> inlined_b; |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
inlined_b.emplace_back(1); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
inlined_a = std::move(inlined_b); |
|
|
|
inlined_a = std::move(inlined_b); |
|
|
|
// Moved elements
|
|
|
|
// Moved elements
|
|
|
|
EXPECT_EQ(tracker.moves(), 1); |
|
|
|
EXPECT_EQ(tracker.moves(), 1); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 1); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 1); |
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(inlined_a, Pointwise(HasValue(), {1})); |
|
|
|
EXPECT_THAT(inlined_a, Pointwise(HasValue(), {1})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
TEST(NonAssignableMoveAssignmentTest, AllocatedToAllocated) { |
|
|
|
InstanceTracker tracker; |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
absl::InlinedVector<X, 2> allocated_a; |
|
|
|
InstanceTracker tracker; |
|
|
|
allocated_a.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> allocated_a; |
|
|
|
allocated_a.emplace_back(2); |
|
|
|
allocated_a.emplace_back(1); |
|
|
|
allocated_a.emplace_back(3); |
|
|
|
allocated_a.emplace_back(2); |
|
|
|
absl::InlinedVector<X, 2> allocated_b; |
|
|
|
allocated_a.emplace_back(3); |
|
|
|
allocated_b.emplace_back(4); |
|
|
|
absl::InlinedVector<X, 2> allocated_b; |
|
|
|
allocated_b.emplace_back(5); |
|
|
|
allocated_b.emplace_back(4); |
|
|
|
allocated_b.emplace_back(6); |
|
|
|
allocated_b.emplace_back(5); |
|
|
|
allocated_b.emplace_back(7); |
|
|
|
allocated_b.emplace_back(6); |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
allocated_b.emplace_back(7); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
allocated_a = std::move(allocated_b); |
|
|
|
allocated_a = std::move(allocated_b); |
|
|
|
// passed ownership of the allocated storage
|
|
|
|
// passed ownership of the allocated storage
|
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 4); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 4); |
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7})); |
|
|
|
EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
TEST(NonAssignableMoveAssignmentTest, AssignThis) { |
|
|
|
InstanceTracker tracker; |
|
|
|
using X = MoveConstructibleOnlyInstance; |
|
|
|
absl::InlinedVector<X, 2> v; |
|
|
|
InstanceTracker tracker; |
|
|
|
v.emplace_back(1); |
|
|
|
absl::InlinedVector<X, 2> v; |
|
|
|
v.emplace_back(2); |
|
|
|
v.emplace_back(1); |
|
|
|
v.emplace_back(3); |
|
|
|
v.emplace_back(2); |
|
|
|
|
|
|
|
v.emplace_back(3); |
|
|
|
|
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
// Obfuscated in order to pass -Wself-move.
|
|
|
|
// Obfuscated in order to pass -Wself-move.
|
|
|
|
v = std::move(*std::addressof(v)); |
|
|
|
v = std::move(*std::addressof(v)); |
|
|
|
// nothing happens
|
|
|
|
// nothing happens
|
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 3); |
|
|
|
EXPECT_EQ(tracker.live_instances(), 3); |
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NonSwappableInstance : public absl::test_internal::BaseCountedInstance { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
explicit NonSwappableInstance(int x) : BaseCountedInstance(x) {} |
|
|
|
|
|
|
|
NonSwappableInstance(const NonSwappableInstance& other) = default; |
|
|
|
|
|
|
|
NonSwappableInstance& operator=(const NonSwappableInstance& other) = default; |
|
|
|
|
|
|
|
NonSwappableInstance(NonSwappableInstance&& other) = default; |
|
|
|
|
|
|
|
NonSwappableInstance& operator=(NonSwappableInstance&& other) = default; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void swap(NonSwappableInstance&, NonSwappableInstance&) = delete; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST(NonSwappableSwapTest, InlineAndAllocatedTransferStorageAndMove) { |
|
|
|
|
|
|
|
using X = NonSwappableInstance; |
|
|
|
|
|
|
|
InstanceTracker tracker; |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> inlined; |
|
|
|
|
|
|
|
inlined.emplace_back(1); |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> allocated; |
|
|
|
|
|
|
|
allocated.emplace_back(1); |
|
|
|
|
|
|
|
allocated.emplace_back(2); |
|
|
|
|
|
|
|
allocated.emplace_back(3); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inlined.swap(allocated); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.moves(), 1); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.live_instances(), 4); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST(NonSwappableSwapTest, InlineAndInlineMoveIndividualElements) { |
|
|
|
|
|
|
|
using X = NonSwappableInstance; |
|
|
|
|
|
|
|
InstanceTracker tracker; |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> inlined_a; |
|
|
|
|
|
|
|
inlined_a.emplace_back(1); |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> inlined_b; |
|
|
|
|
|
|
|
inlined_b.emplace_back(2); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inlined_a.swap(inlined_b); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.moves(), 3); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.live_instances(), 2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(inlined_a, Pointwise(HasValue(), {2})); |
|
|
|
|
|
|
|
EXPECT_THAT(inlined_b, Pointwise(HasValue(), {1})); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST(NonSwappableSwapTest, AllocatedAndAllocatedOnlyTransferStorage) { |
|
|
|
|
|
|
|
using X = NonSwappableInstance; |
|
|
|
|
|
|
|
InstanceTracker tracker; |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> allocated_a; |
|
|
|
|
|
|
|
allocated_a.emplace_back(1); |
|
|
|
|
|
|
|
allocated_a.emplace_back(2); |
|
|
|
|
|
|
|
allocated_a.emplace_back(3); |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> allocated_b; |
|
|
|
|
|
|
|
allocated_b.emplace_back(4); |
|
|
|
|
|
|
|
allocated_b.emplace_back(5); |
|
|
|
|
|
|
|
allocated_b.emplace_back(6); |
|
|
|
|
|
|
|
allocated_b.emplace_back(7); |
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
allocated_a.swap(allocated_b); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.live_instances(), 7); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7})); |
|
|
|
|
|
|
|
EXPECT_THAT(allocated_b, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST(NonSwappableSwapTest, SwapThis) { |
|
|
|
|
|
|
|
using X = NonSwappableInstance; |
|
|
|
|
|
|
|
InstanceTracker tracker; |
|
|
|
|
|
|
|
absl::InlinedVector<X, 2> v; |
|
|
|
|
|
|
|
v.emplace_back(1); |
|
|
|
|
|
|
|
v.emplace_back(2); |
|
|
|
|
|
|
|
v.emplace_back(3); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tracker.ResetCopiesMovesSwaps(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v.swap(v); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.moves(), 0); |
|
|
|
|
|
|
|
EXPECT_EQ(tracker.live_instances(), 3); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
} // anonymous namespace
|
|
|
|