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