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/CPP/ArrayRef.h" 10 #include "src/string/memmove.h" 11 #include "utils/UnitTest/MemoryMatcher.h" 12 #include "utils/UnitTest/Test.h" 13 14 using __llvm_libc::cpp::Array; 15 using __llvm_libc::cpp::ArrayRef; 16 using __llvm_libc::cpp::MutableArrayRef; 17 18 TEST(LlvmLibcMemmoveTest, MoveZeroByte) { 19 char Buffer[] = {'a', 'b', 'y', 'z'}; 20 const char Expected[] = {'a', 'b', 'y', 'z'}; 21 void *const Dst = Buffer; 22 void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 0); 23 EXPECT_EQ(Ret, Dst); 24 EXPECT_MEM_EQ(Buffer, Expected); 25 } 26 27 TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) { 28 char Buffer[] = {'a', 'b'}; 29 const char Expected[] = {'a', 'b'}; 30 void *const Dst = Buffer; 31 void *const Ret = __llvm_libc::memmove(Dst, Buffer, 1); 32 EXPECT_EQ(Ret, Dst); 33 EXPECT_MEM_EQ(Buffer, Expected); 34 } 35 36 TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) { 37 // Set boundary at beginning and end for not overstepping when 38 // copy forward or backward. 39 char Buffer[] = {'z', 'a', 'b', 'c', 'z'}; 40 const char Expected[] = {'z', 'b', 'c', 'c', 'z'}; 41 void *const Dst = Buffer + 1; 42 void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 2); 43 EXPECT_EQ(Ret, Dst); 44 EXPECT_MEM_EQ(Buffer, Expected); 45 } 46 47 TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) { 48 char Buffer[] = {'z', 'a', 'b', 'c', 'z'}; 49 const char Expected[] = {'z', 'a', 'a', 'b', 'z'}; 50 void *const Dst = Buffer + 2; 51 void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 2); 52 EXPECT_EQ(Ret, Dst); 53 EXPECT_MEM_EQ(Buffer, Expected); 54 } 55 56 // e.g. `Dst` follow `src`. 57 // str: [abcdefghij] 58 // [__src_____] 59 // [_____Dst__] 60 TEST(LlvmLibcMemmoveTest, SrcFollowDst) { 61 char Buffer[] = {'z', 'a', 'b', 'z'}; 62 const char Expected[] = {'z', 'b', 'b', 'z'}; 63 void *const Dst = Buffer + 1; 64 void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 1); 65 EXPECT_EQ(Ret, Dst); 66 EXPECT_MEM_EQ(Buffer, Expected); 67 } 68 69 TEST(LlvmLibcMemmoveTest, DstFollowSrc) { 70 char Buffer[] = {'z', 'a', 'b', 'z'}; 71 const char Expected[] = {'z', 'a', 'a', 'z'}; 72 void *const Dst = Buffer + 2; 73 void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 1); 74 EXPECT_EQ(Ret, Dst); 75 EXPECT_MEM_EQ(Buffer, Expected); 76 } 77 78 static constexpr int kMaxSize = 512; 79 80 char GetRandomChar() { 81 static constexpr const uint64_t A = 1103515245; 82 static constexpr const uint64_t C = 12345; 83 static constexpr const uint64_t M = 1ULL << 31; 84 static uint64_t Seed = 123456789; 85 Seed = (A * Seed + C) % M; 86 return Seed; 87 } 88 89 void Randomize(MutableArrayRef<char> Buffer) { 90 for (auto ¤t : Buffer) 91 current = GetRandomChar(); 92 } 93 94 TEST(LlvmLibcMemmoveTest, Thorough) { 95 using LargeBuffer = Array<char, 3 * kMaxSize>; 96 LargeBuffer GroundTruth; 97 Randomize(GroundTruth); 98 for (int Size = 0; Size < kMaxSize; ++Size) { 99 for (int Offset = -Size; Offset < Size; ++Offset) { 100 LargeBuffer Buffer = GroundTruth; 101 LargeBuffer Expected = GroundTruth; 102 size_t DstOffset = kMaxSize; 103 size_t SrcOffset = kMaxSize + Offset; 104 for (int I = 0; I < Size; ++I) 105 Expected[DstOffset + I] = GroundTruth[SrcOffset + I]; 106 void *const Dst = Buffer.data() + DstOffset; 107 void *const Ret = 108 __llvm_libc::memmove(Dst, Buffer.data() + SrcOffset, Size); 109 EXPECT_EQ(Ret, Dst); 110 EXPECT_MEM_EQ(Buffer, Expected); 111 } 112 } 113 } 114