| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// \file | |
| /// Unit tests for swap. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #include "hdr/stdint_proxy.h" | |
| #include "src/__support/CPP/utility/swap.h" | |
| #include "src/__support/macros/config.h" | |
| #include "test/UnitTest/Test.h" | |
| namespace LIBC_NAMESPACE_DECL { | |
| namespace cpp { | |
| TEST(LlvmLibcSwapTest, Primitives) { | |
| int a = 10; | |
| int b = 20; | |
| swap(a, b); | |
| EXPECT_EQ(a, 20); | |
| EXPECT_EQ(b, 10); | |
| char c1 = 'x'; | |
| char c2 = 'y'; | |
| swap(c1, c2); | |
| EXPECT_EQ(c1, 'y'); | |
| EXPECT_EQ(c2, 'x'); | |
| uint64_t u1 = 0x123456789abcdef0; | |
| uint64_t u2 = 0x0fedcba987654321; | |
| swap(u1, u2); | |
| EXPECT_EQ(u1, uint64_t(0x0fedcba987654321)); | |
| EXPECT_EQ(u2, uint64_t(0x123456789abcdef0)); | |
| } | |
| struct MoveTracker { | |
| int val = 0; | |
| int moves = 0; | |
| int copies = 0; | |
| constexpr MoveTracker(int v) : val(v) {} | |
| constexpr MoveTracker(const MoveTracker &o) | |
| : val(o.val), moves(o.moves), copies(o.copies + 1) {} | |
| constexpr MoveTracker(MoveTracker &&o) | |
| : val(o.val), moves(o.moves + 1), copies(o.copies) { | |
| o.val = 0; | |
| } | |
| constexpr MoveTracker &operator=(const MoveTracker &o) { | |
| val = o.val; | |
| copies = o.copies + 1; | |
| return *this; | |
| } | |
| constexpr MoveTracker &operator=(MoveTracker &&o) { | |
| val = o.val; | |
| moves = o.moves + 1; | |
| o.val = 0; | |
| return *this; | |
| } | |
| }; | |
| TEST(LlvmLibcSwapTest, MoveSemantics) { | |
| MoveTracker t1(100); | |
| MoveTracker t2(200); | |
| swap(t1, t2); | |
| EXPECT_EQ(t1.val, 200); | |
| EXPECT_EQ(t2.val, 100); | |
| // swap should perform 3 moves and 0 copies | |
| EXPECT_EQ(t1.copies, 0); | |
| EXPECT_EQ(t2.copies, 0); | |
| EXPECT_EQ(t1.moves + t2.moves, 3); | |
| } | |
| struct MoveOnly { | |
| int val; | |
| constexpr MoveOnly(int v) : val(v) {} | |
| MoveOnly(const MoveOnly &) = delete; | |
| MoveOnly &operator=(const MoveOnly &) = delete; | |
| constexpr MoveOnly(MoveOnly &&o) : val(o.val) { o.val = 0; } | |
| constexpr MoveOnly &operator=(MoveOnly &&o) { | |
| val = o.val; | |
| o.val = 0; | |
| return *this; | |
| } | |
| }; | |
| TEST(LlvmLibcSwapTest, MoveOnlyType) { | |
| MoveOnly m1(1); | |
| MoveOnly m2(2); | |
| swap(m1, m2); | |
| EXPECT_EQ(m1.val, 2); | |
| EXPECT_EQ(m2.val, 1); | |
| } | |
| TEST(LlvmLibcSwapTest, ArraySwap) { | |
| int arr1[3] = {1, 2, 3}; | |
| int arr2[3] = {4, 5, 6}; | |
| swap(arr1, arr2); | |
| EXPECT_EQ(arr1[0], 4); | |
| EXPECT_EQ(arr1[1], 5); | |
| EXPECT_EQ(arr1[2], 6); | |
| EXPECT_EQ(arr2[0], 1); | |
| EXPECT_EQ(arr2[1], 2); | |
| EXPECT_EQ(arr2[2], 3); | |
| } | |
| } // namespace cpp | |
| } // namespace LIBC_NAMESPACE_DECL |