xref: /llvm-project/libc/test/src/string/memmove_test.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
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 
9*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
102423ec58SCheng Wang #include "src/string/memmove.h"
114e298c32SRoland McGrath 
124e298c32SRoland McGrath #include "memory_utils/memory_check_utils.h"
134e298c32SRoland McGrath #include "src/__support/CPP/span.h"
14af1315c2SSiva Chandra Reddy #include "test/UnitTest/MemoryMatcher.h"
15af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
162423ec58SCheng Wang 
17b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::cpp::array;
18b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::cpp::span;
192423ec58SCheng Wang 
20*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
21298843cdSGuillaume Chatelet 
2283f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, MoveZeroByte) {
2383f9b13dSGuillaume Chatelet   char Buffer[] = {'a', 'b', 'y', 'z'};
2483f9b13dSGuillaume Chatelet   const char Expected[] = {'a', 'b', 'y', 'z'};
2583f9b13dSGuillaume Chatelet   void *const Dst = Buffer;
26b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 0);
2783f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
289902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
292423ec58SCheng Wang }
302423ec58SCheng Wang 
3183f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) {
3283f9b13dSGuillaume Chatelet   char Buffer[] = {'a', 'b'};
3383f9b13dSGuillaume Chatelet   const char Expected[] = {'a', 'b'};
3483f9b13dSGuillaume Chatelet   void *const Dst = Buffer;
35b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer, 1);
3683f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
379902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
382423ec58SCheng Wang }
392423ec58SCheng Wang 
4083f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) {
412423ec58SCheng Wang   // Set boundary at beginning and end for not overstepping when
422423ec58SCheng Wang   // copy forward or backward.
4383f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
4483f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'b', 'c', 'c', 'z'};
4583f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 1;
46b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 2);
4783f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
489902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
492423ec58SCheng Wang }
502423ec58SCheng Wang 
5183f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) {
5283f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
5383f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'a', 'a', 'b', 'z'};
5483f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 2;
55b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 2);
5683f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
579902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
582423ec58SCheng Wang }
592423ec58SCheng Wang 
6083f9b13dSGuillaume Chatelet // e.g. `Dst` follow `src`.
612423ec58SCheng Wang // str: [abcdefghij]
622423ec58SCheng Wang //      [__src_____]
6383f9b13dSGuillaume Chatelet //      [_____Dst__]
6483f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, SrcFollowDst) {
6583f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'z'};
6683f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'b', 'b', 'z'};
6783f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 1;
68b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 1);
6983f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
709902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
712423ec58SCheng Wang }
722423ec58SCheng Wang 
7383f9b13dSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, DstFollowSrc) {
7483f9b13dSGuillaume Chatelet   char Buffer[] = {'z', 'a', 'b', 'z'};
7583f9b13dSGuillaume Chatelet   const char Expected[] = {'z', 'a', 'a', 'z'};
7683f9b13dSGuillaume Chatelet   void *const Dst = Buffer + 2;
77b6bc9d72SGuillaume Chatelet   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 1);
7883f9b13dSGuillaume Chatelet   EXPECT_EQ(Ret, Dst);
799902fc8dSGuillaume Chatelet   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
8083f9b13dSGuillaume Chatelet }
8183f9b13dSGuillaume Chatelet 
82298843cdSGuillaume Chatelet // Adapt CheckMemmove signature to op implementation signatures.
83298843cdSGuillaume Chatelet static inline void Adaptor(cpp::span<char> dst, cpp::span<char> src,
84298843cdSGuillaume Chatelet                            size_t size) {
85b6bc9d72SGuillaume Chatelet   LIBC_NAMESPACE::memmove(dst.begin(), src.begin(), size);
86298843cdSGuillaume Chatelet }
8783f9b13dSGuillaume Chatelet 
883635195eSGuillaume Chatelet TEST(LlvmLibcMemmoveTest, SizeSweep) {
89298843cdSGuillaume Chatelet   static constexpr int kMaxSize = 400;
90298843cdSGuillaume Chatelet   static constexpr int kDenseOverlap = 15;
91298843cdSGuillaume Chatelet   using LargeBuffer = array<char, 2 * kMaxSize + 1>;
92298843cdSGuillaume Chatelet   LargeBuffer Buffer;
93298843cdSGuillaume Chatelet   Randomize(Buffer);
94298843cdSGuillaume Chatelet   for (int Size = 0; Size < kMaxSize; ++Size)
95298843cdSGuillaume Chatelet     for (int Overlap = -1; Overlap < Size;) {
96298843cdSGuillaume Chatelet       ASSERT_TRUE(CheckMemmove<Adaptor>(Buffer, Size, Overlap));
97298843cdSGuillaume Chatelet       // Prevent quadratic behavior by skipping offset above kDenseOverlap.
98298843cdSGuillaume Chatelet       if (Overlap > kDenseOverlap)
99298843cdSGuillaume Chatelet         Overlap *= 2;
100298843cdSGuillaume Chatelet       else
101298843cdSGuillaume Chatelet         ++Overlap;
10283f9b13dSGuillaume Chatelet     }
10383f9b13dSGuillaume Chatelet }
104298843cdSGuillaume Chatelet 
105*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
106