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 &current : 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