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
16using LIBC_NAMESPACE::cpp::array;
17using LIBC_NAMESPACE::cpp::span;
18
19namespace LIBC_NAMESPACE {
20
21TEST(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: Dst, src: Buffer + 2, count: 0);
26 EXPECT_EQ(Ret, Dst);
27 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
28}
29
30TEST(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: Dst, src: Buffer, count: 1);
35 EXPECT_EQ(Ret, Dst);
36 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
37}
38
39TEST(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: Dst, src: Buffer + 2, count: 2);
46 EXPECT_EQ(Ret, Dst);
47 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
48}
49
50TEST(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: Dst, src: Buffer + 1, count: 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__]
63TEST(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: Dst, src: Buffer + 2, count: 1);
68 EXPECT_EQ(Ret, Dst);
69 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
70}
71
72TEST(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: Dst, src: Buffer + 1, count: 1);
77 EXPECT_EQ(Ret, Dst);
78 ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
79}
80
81// Adapt CheckMemmove signature to op implementation signatures.
82static inline void Adaptor(cpp::span<char> dst, cpp::span<char> src,
83 size_t size) {
84 LIBC_NAMESPACE::memmove(dst: dst.begin(), src: src.begin(), count: size);
85}
86
87TEST(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: 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

source code of libc/test/src/string/memmove_test.cpp