1 //===-- Unittests for memmove ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/__support/macros/config.h" 10 #include "src/string/memmove.h" 11 12 #include "memory_utils/memory_check_utils.h" 13 #include "src/__support/CPP/span.h" 14 #include "test/UnitTest/MemoryMatcher.h" 15 #include "test/UnitTest/Test.h" 16 17 using LIBC_NAMESPACE::cpp::array; 18 using LIBC_NAMESPACE::cpp::span; 19 20 namespace LIBC_NAMESPACE_DECL { 21 22 TEST(LlvmLibcMemmoveTest, MoveZeroByte) { 23 char Buffer[] = {'a', 'b', 'y', 'z'}; 24 const char Expected[] = {'a', 'b', 'y', 'z'}; 25 void *const Dst = Buffer; 26 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 0); 27 EXPECT_EQ(Ret, Dst); 28 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 29 } 30 31 TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) { 32 char Buffer[] = {'a', 'b'}; 33 const char Expected[] = {'a', 'b'}; 34 void *const Dst = Buffer; 35 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer, 1); 36 EXPECT_EQ(Ret, Dst); 37 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 38 } 39 40 TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) { 41 // Set boundary at beginning and end for not overstepping when 42 // copy forward or backward. 43 char Buffer[] = {'z', 'a', 'b', 'c', 'z'}; 44 const char Expected[] = {'z', 'b', 'c', 'c', 'z'}; 45 void *const Dst = Buffer + 1; 46 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 2); 47 EXPECT_EQ(Ret, Dst); 48 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 49 } 50 51 TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) { 52 char Buffer[] = {'z', 'a', 'b', 'c', 'z'}; 53 const char Expected[] = {'z', 'a', 'a', 'b', 'z'}; 54 void *const Dst = Buffer + 2; 55 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 2); 56 EXPECT_EQ(Ret, Dst); 57 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 58 } 59 60 // e.g. `Dst` follow `src`. 61 // str: [abcdefghij] 62 // [__src_____] 63 // [_____Dst__] 64 TEST(LlvmLibcMemmoveTest, SrcFollowDst) { 65 char Buffer[] = {'z', 'a', 'b', 'z'}; 66 const char Expected[] = {'z', 'b', 'b', 'z'}; 67 void *const Dst = Buffer + 1; 68 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 1); 69 EXPECT_EQ(Ret, Dst); 70 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 71 } 72 73 TEST(LlvmLibcMemmoveTest, DstFollowSrc) { 74 char Buffer[] = {'z', 'a', 'b', 'z'}; 75 const char Expected[] = {'z', 'a', 'a', 'z'}; 76 void *const Dst = Buffer + 2; 77 void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 1); 78 EXPECT_EQ(Ret, Dst); 79 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected)); 80 } 81 82 // Adapt CheckMemmove signature to op implementation signatures. 83 static inline void Adaptor(cpp::span<char> dst, cpp::span<char> src, 84 size_t size) { 85 LIBC_NAMESPACE::memmove(dst.begin(), src.begin(), size); 86 } 87 88 TEST(LlvmLibcMemmoveTest, SizeSweep) { 89 static constexpr int kMaxSize = 400; 90 static constexpr int kDenseOverlap = 15; 91 using LargeBuffer = array<char, 2 * kMaxSize + 1>; 92 LargeBuffer Buffer; 93 Randomize(Buffer); 94 for (int Size = 0; Size < kMaxSize; ++Size) 95 for (int Overlap = -1; Overlap < Size;) { 96 ASSERT_TRUE(CheckMemmove<Adaptor>(Buffer, Size, Overlap)); 97 // Prevent quadratic behavior by skipping offset above kDenseOverlap. 98 if (Overlap > kDenseOverlap) 99 Overlap *= 2; 100 else 101 ++Overlap; 102 } 103 } 104 105 } // namespace LIBC_NAMESPACE_DECL 106