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
TEST(LlvmLibcMemmoveTest,MoveZeroByte)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
TEST(LlvmLibcMemmoveTest,DstAndSrcPointToSameAddress)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
TEST(LlvmLibcMemmoveTest,DstStartsBeforeSrc)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
TEST(LlvmLibcMemmoveTest,DstStartsAfterSrc)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__]
TEST(LlvmLibcMemmoveTest,SrcFollowDst)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
TEST(LlvmLibcMemmoveTest,DstFollowSrc)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
GetRandomChar()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
Randomize(MutableArrayRef<char> Buffer)89 void Randomize(MutableArrayRef<char> Buffer) {
90 for (auto ¤t : Buffer)
91 current = GetRandomChar();
92 }
93
TEST(LlvmLibcMemmoveTest,Thorough)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