12423ec58SCheng Wang //===-- Unittests for memmove ---------------------------------------------===//
22423ec58SCheng Wang //
32423ec58SCheng Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42423ec58SCheng Wang // See https://llvm.org/LICENSE.txt for license information.
52423ec58SCheng Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62423ec58SCheng Wang //
72423ec58SCheng Wang //===----------------------------------------------------------------------===//
82423ec58SCheng Wang 
9f362aea4SSiva Chandra Reddy #include "src/__support/CPP/ArrayRef.h"
102423ec58SCheng Wang #include "src/string/memmove.h"
11*83f9b13dSGuillaume Chatelet #include "utils/UnitTest/MemoryMatcher.h"
122423ec58SCheng Wang #include "utils/UnitTest/Test.h"
132423ec58SCheng Wang 
14*83f9b13dSGuillaume Chatelet using __llvm_libc::cpp::Array;
15*83f9b13dSGuillaume Chatelet using __llvm_libc::cpp::ArrayRef;
16*83f9b13dSGuillaume Chatelet using __llvm_libc::cpp::MutableArrayRef;
172423ec58SCheng Wang 
TEST(LlvmLibcMemmoveTest,MoveZeroByte)18*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, MoveZeroByte) {
19*83f9b13dSGuillaume Chatelet   char Buffer[] = {'a', 'b', 'y', 'z'};
20*83f9b13dSGuillaume Chatelet   const char Expected[] = {'a', 'b', 'y', 'z'};
21*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer;
22*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 0);
23*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
24*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
252423ec58SCheng Wang }
262423ec58SCheng Wang 
TEST(LlvmLibcMemmoveTest,DstAndSrcPointToSameAddress)27*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) {
28*83f9b13dSGuillaume Chatelet   char Buffer[] = {'a', 'b'};
29*83f9b13dSGuillaume Chatelet   const char Expected[] = {'a', 'b'};
30*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer;
31*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer, 1);
32*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
33*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
342423ec58SCheng Wang }
352423ec58SCheng Wang 
TEST(LlvmLibcMemmoveTest,DstStartsBeforeSrc)36*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) {
372423ec58SCheng Wang   // Set boundary at beginning and end for not overstepping when
382423ec58SCheng Wang   // copy forward or backward.
39*83f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
40*83f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'b', 'c', 'c', 'z'};
41*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 1;
42*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 2);
43*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
44*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
452423ec58SCheng Wang }
462423ec58SCheng Wang 
TEST(LlvmLibcMemmoveTest,DstStartsAfterSrc)47*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) {
48*83f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
49*83f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'a', 'a', 'b', 'z'};
50*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 2;
51*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 2);
52*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
53*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
542423ec58SCheng Wang }
552423ec58SCheng Wang 
56*83f9b13dSGuillaume Chatelet // e.g. `Dst` follow `src`.
572423ec58SCheng Wang // str: [abcdefghij]
582423ec58SCheng Wang //      [__src_____]
59*83f9b13dSGuillaume Chatelet //      [_____Dst__]
TEST(LlvmLibcMemmoveTest,SrcFollowDst)60*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, SrcFollowDst) {
61*83f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'z'};
62*83f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'b', 'b', 'z'};
63*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 1;
64*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer + 2, 1);
65*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
66*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
672423ec58SCheng Wang }
682423ec58SCheng Wang 
TEST(LlvmLibcMemmoveTest,DstFollowSrc)69*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstFollowSrc) {
70*83f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'z'};
71*83f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'a', 'a', 'z'};
72*83f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 2;
73*83f9b13dSGuillaume Chatelet   void *const Ret = __llvm_libc::memmove(Dst, Buffer + 1, 1);
74*83f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
75*83f9b13dSGuillaume Chatelet   EXPECT_MEM_EQ(Buffer, Expected);
76*83f9b13dSGuillaume Chatelet }
77*83f9b13dSGuillaume Chatelet 
78*83f9b13dSGuillaume Chatelet static constexpr int kMaxSize = 512;
79*83f9b13dSGuillaume Chatelet 
GetRandomChar()80*83f9b13dSGuillaume Chatelet char GetRandomChar() {
81*83f9b13dSGuillaume Chatelet   static constexpr const uint64_t A = 1103515245;
82*83f9b13dSGuillaume Chatelet   static constexpr const uint64_t C = 12345;
83*83f9b13dSGuillaume Chatelet   static constexpr const uint64_t M = 1ULL << 31;
84*83f9b13dSGuillaume Chatelet   static uint64_t Seed = 123456789;
85*83f9b13dSGuillaume Chatelet   Seed = (A * Seed + C) % M;
86*83f9b13dSGuillaume Chatelet   return Seed;
87*83f9b13dSGuillaume Chatelet }
88*83f9b13dSGuillaume Chatelet 
Randomize(MutableArrayRef<char> Buffer)89*83f9b13dSGuillaume Chatelet void Randomize(MutableArrayRef<char> Buffer) {
90*83f9b13dSGuillaume Chatelet   for (auto &current : Buffer)
91*83f9b13dSGuillaume Chatelet     current = GetRandomChar();
92*83f9b13dSGuillaume Chatelet }
93*83f9b13dSGuillaume Chatelet 
TEST(LlvmLibcMemmoveTest,Thorough)94*83f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, Thorough) {
95*83f9b13dSGuillaume Chatelet   using LargeBuffer = Array<char, 3 * kMaxSize>;
96*83f9b13dSGuillaume Chatelet   LargeBuffer GroundTruth;
97*83f9b13dSGuillaume Chatelet   Randomize(GroundTruth);
98*83f9b13dSGuillaume Chatelet   for (int Size = 0; Size < kMaxSize; ++Size) {
99*83f9b13dSGuillaume Chatelet     for (int Offset = -Size; Offset < Size; ++Offset) {
100*83f9b13dSGuillaume Chatelet       LargeBuffer Buffer = GroundTruth;
101*83f9b13dSGuillaume Chatelet       LargeBuffer Expected = GroundTruth;
102*83f9b13dSGuillaume Chatelet       size_t DstOffset = kMaxSize;
103*83f9b13dSGuillaume Chatelet       size_t SrcOffset = kMaxSize + Offset;
104*83f9b13dSGuillaume Chatelet       for (int I = 0; I < Size; ++I)
105*83f9b13dSGuillaume Chatelet         Expected[DstOffset + I] = GroundTruth[SrcOffset + I];
106*83f9b13dSGuillaume Chatelet       void *const Dst = Buffer.data() + DstOffset;
107*83f9b13dSGuillaume Chatelet       void *const Ret =
108*83f9b13dSGuillaume Chatelet           __llvm_libc::memmove(Dst, Buffer.data() + SrcOffset, Size);
109*83f9b13dSGuillaume Chatelet       EXPECT_EQ(Ret, Dst);
110*83f9b13dSGuillaume Chatelet       EXPECT_MEM_EQ(Buffer, Expected);
111*83f9b13dSGuillaume Chatelet     }
112*83f9b13dSGuillaume Chatelet   }
1132423ec58SCheng Wang }
114