• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/string/memmove.h"
10 
11 #include "memory_utils/memory_check_utils.h"
12 #include "src/__support/CPP/span.h"
13 #include "test/UnitTest/MemoryMatcher.h"
14 #include "test/UnitTest/Test.h"
15 
16 using LIBC_NAMESPACE::cpp::array;
17 using LIBC_NAMESPACE::cpp::span;
18 
19 namespace LIBC_NAMESPACE {
20 
TEST(LlvmLibcMemmoveTest,MoveZeroByte)21 TEST(LlvmLibcMemmoveTest, MoveZeroByte) {
22   char Buffer[] = {'a', 'b', 'y', 'z'};
23   const char Expected[] = {'a', 'b', 'y', 'z'};
24   void *const Dst = Buffer;
25   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 0);
26   EXPECT_EQ(Ret, Dst);
27   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
28 }
29 
TEST(LlvmLibcMemmoveTest,DstAndSrcPointToSameAddress)30 TEST(LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) {
31   char Buffer[] = {'a', 'b'};
32   const char Expected[] = {'a', 'b'};
33   void *const Dst = Buffer;
34   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer, 1);
35   EXPECT_EQ(Ret, Dst);
36   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
37 }
38 
TEST(LlvmLibcMemmoveTest,DstStartsBeforeSrc)39 TEST(LlvmLibcMemmoveTest, DstStartsBeforeSrc) {
40   // Set boundary at beginning and end for not overstepping when
41   // copy forward or backward.
42   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
43   const char Expected[] = {'z', 'b', 'c', 'c', 'z'};
44   void *const Dst = Buffer + 1;
45   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 2);
46   EXPECT_EQ(Ret, Dst);
47   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
48 }
49 
TEST(LlvmLibcMemmoveTest,DstStartsAfterSrc)50 TEST(LlvmLibcMemmoveTest, DstStartsAfterSrc) {
51   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
52   const char Expected[] = {'z', 'a', 'a', 'b', 'z'};
53   void *const Dst = Buffer + 2;
54   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 2);
55   EXPECT_EQ(Ret, Dst);
56   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
57 }
58 
59 // e.g. `Dst` follow `src`.
60 // str: [abcdefghij]
61 //      [__src_____]
62 //      [_____Dst__]
TEST(LlvmLibcMemmoveTest,SrcFollowDst)63 TEST(LlvmLibcMemmoveTest, SrcFollowDst) {
64   char Buffer[] = {'z', 'a', 'b', 'z'};
65   const char Expected[] = {'z', 'b', 'b', 'z'};
66   void *const Dst = Buffer + 1;
67   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 2, 1);
68   EXPECT_EQ(Ret, Dst);
69   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
70 }
71 
TEST(LlvmLibcMemmoveTest,DstFollowSrc)72 TEST(LlvmLibcMemmoveTest, DstFollowSrc) {
73   char Buffer[] = {'z', 'a', 'b', 'z'};
74   const char Expected[] = {'z', 'a', 'a', 'z'};
75   void *const Dst = Buffer + 2;
76   void *const Ret = LIBC_NAMESPACE::memmove(Dst, Buffer + 1, 1);
77   EXPECT_EQ(Ret, Dst);
78   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
79 }
80 
81 // Adapt CheckMemmove signature to op implementation signatures.
Adaptor(cpp::span<char> dst,cpp::span<char> src,size_t size)82 static inline void Adaptor(cpp::span<char> dst, cpp::span<char> src,
83                            size_t size) {
84   LIBC_NAMESPACE::memmove(dst.begin(), src.begin(), size);
85 }
86 
TEST(LlvmLibcMemmoveTest,SizeSweep)87 TEST(LlvmLibcMemmoveTest, SizeSweep) {
88   static constexpr int kMaxSize = 400;
89   static constexpr int kDenseOverlap = 15;
90   using LargeBuffer = array<char, 2 * kMaxSize + 1>;
91   LargeBuffer Buffer;
92   Randomize(Buffer);
93   for (int Size = 0; Size < kMaxSize; ++Size)
94     for (int Overlap = -1; Overlap < Size;) {
95       ASSERT_TRUE(CheckMemmove<Adaptor>(Buffer, Size, Overlap));
96       // Prevent quadratic behavior by skipping offset above kDenseOverlap.
97       if (Overlap > kDenseOverlap)
98         Overlap *= 2;
99       else
100         ++Overlap;
101     }
102 }
103 
104 } // namespace LIBC_NAMESPACE
105