xref: /llvm-project/libc/test/src/strings/bcopy_test.cpp (revision 431ea2d076f8a5ca35b2c293dd5d62f5ce083f45)
1*431ea2d0SNick Desaulniers //===-- Unittests for bcopy -----------------------------------------------===//
2*431ea2d0SNick Desaulniers //
3*431ea2d0SNick Desaulniers // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*431ea2d0SNick Desaulniers // See https://llvm.org/LICENSE.txt for license information.
5*431ea2d0SNick Desaulniers // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*431ea2d0SNick Desaulniers //
7*431ea2d0SNick Desaulniers //===----------------------------------------------------------------------===//
8*431ea2d0SNick Desaulniers 
9*431ea2d0SNick Desaulniers #include "src/strings/bcopy.h"
10*431ea2d0SNick Desaulniers 
11*431ea2d0SNick Desaulniers #include "src/__support/CPP/span.h"
12*431ea2d0SNick Desaulniers #include "src/__support/macros/config.h"
13*431ea2d0SNick Desaulniers #include "test/UnitTest/MemoryMatcher.h"
14*431ea2d0SNick Desaulniers #include "test/UnitTest/Test.h"
15*431ea2d0SNick Desaulniers #include "test/src/string/memory_utils/memory_check_utils.h"
16*431ea2d0SNick Desaulniers 
17*431ea2d0SNick Desaulniers using LIBC_NAMESPACE::cpp::array;
18*431ea2d0SNick Desaulniers using LIBC_NAMESPACE::cpp::span;
19*431ea2d0SNick Desaulniers 
20*431ea2d0SNick Desaulniers namespace LIBC_NAMESPACE_DECL {
21*431ea2d0SNick Desaulniers 
22*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, MoveZeroByte) {
23*431ea2d0SNick Desaulniers   char Buffer[] = {'a', 'b', 'y', 'z'};
24*431ea2d0SNick Desaulniers   const char Expected[] = {'a', 'b', 'y', 'z'};
25*431ea2d0SNick Desaulniers   void *const Dst = Buffer;
26*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer + 2, Dst, 0);
27*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
28*431ea2d0SNick Desaulniers }
29*431ea2d0SNick Desaulniers 
30*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, DstAndSrcPointToSameAddress) {
31*431ea2d0SNick Desaulniers   char Buffer[] = {'a', 'b'};
32*431ea2d0SNick Desaulniers   const char Expected[] = {'a', 'b'};
33*431ea2d0SNick Desaulniers   void *const Dst = Buffer;
34*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer, Dst, 1);
35*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
36*431ea2d0SNick Desaulniers }
37*431ea2d0SNick Desaulniers 
38*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, DstStartsBeforeSrc) {
39*431ea2d0SNick Desaulniers   // Set boundary at beginning and end for not overstepping when
40*431ea2d0SNick Desaulniers   // copy forward or backward.
41*431ea2d0SNick Desaulniers   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
42*431ea2d0SNick Desaulniers   const char Expected[] = {'z', 'b', 'c', 'c', 'z'};
43*431ea2d0SNick Desaulniers   void *const Dst = Buffer + 1;
44*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer + 2, Dst, 2);
45*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
46*431ea2d0SNick Desaulniers }
47*431ea2d0SNick Desaulniers 
48*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, DstStartsAfterSrc) {
49*431ea2d0SNick Desaulniers   char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
50*431ea2d0SNick Desaulniers   const char Expected[] = {'z', 'a', 'a', 'b', 'z'};
51*431ea2d0SNick Desaulniers   void *const Dst = Buffer + 2;
52*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer + 1, Dst, 2);
53*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
54*431ea2d0SNick Desaulniers }
55*431ea2d0SNick Desaulniers 
56*431ea2d0SNick Desaulniers // e.g. `Dst` follow `src`.
57*431ea2d0SNick Desaulniers // str: [abcdefghij]
58*431ea2d0SNick Desaulniers //      [__src_____]
59*431ea2d0SNick Desaulniers //      [_____Dst__]
60*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, SrcFollowDst) {
61*431ea2d0SNick Desaulniers   char Buffer[] = {'z', 'a', 'b', 'z'};
62*431ea2d0SNick Desaulniers   const char Expected[] = {'z', 'b', 'b', 'z'};
63*431ea2d0SNick Desaulniers   void *const Dst = Buffer + 1;
64*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer + 2, Dst, 1);
65*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
66*431ea2d0SNick Desaulniers }
67*431ea2d0SNick Desaulniers 
68*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, DstFollowSrc) {
69*431ea2d0SNick Desaulniers   char Buffer[] = {'z', 'a', 'b', 'z'};
70*431ea2d0SNick Desaulniers   const char Expected[] = {'z', 'a', 'a', 'z'};
71*431ea2d0SNick Desaulniers   void *const Dst = Buffer + 2;
72*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(Buffer + 1, Dst, 1);
73*431ea2d0SNick Desaulniers   ASSERT_MEM_EQ(Buffer, testing::MemoryView(Expected));
74*431ea2d0SNick Desaulniers }
75*431ea2d0SNick Desaulniers 
76*431ea2d0SNick Desaulniers // Adapt CheckMemmove signature to bcopy.
77*431ea2d0SNick Desaulniers static inline void Adaptor(cpp::span<char> dst, cpp::span<char> src,
78*431ea2d0SNick Desaulniers                            size_t size) {
79*431ea2d0SNick Desaulniers   LIBC_NAMESPACE::bcopy(src.begin(), dst.begin(), size);
80*431ea2d0SNick Desaulniers }
81*431ea2d0SNick Desaulniers 
82*431ea2d0SNick Desaulniers TEST(LlvmLibcBcopyTest, SizeSweep) {
83*431ea2d0SNick Desaulniers   static constexpr int kMaxSize = 400;
84*431ea2d0SNick Desaulniers   static constexpr int kDenseOverlap = 15;
85*431ea2d0SNick Desaulniers   using LargeBuffer = array<char, 2 * kMaxSize + 1>;
86*431ea2d0SNick Desaulniers   LargeBuffer Buffer;
87*431ea2d0SNick Desaulniers   Randomize(Buffer);
88*431ea2d0SNick Desaulniers   for (int Size = 0; Size < kMaxSize; ++Size)
89*431ea2d0SNick Desaulniers     for (int Overlap = -1; Overlap < Size;) {
90*431ea2d0SNick Desaulniers       ASSERT_TRUE(CheckMemmove<Adaptor>(Buffer, Size, Overlap));
91*431ea2d0SNick Desaulniers       // Prevent quadratic behavior by skipping offset above kDenseOverlap.
92*431ea2d0SNick Desaulniers       if (Overlap > kDenseOverlap)
93*431ea2d0SNick Desaulniers         Overlap *= 2;
94*431ea2d0SNick Desaulniers       else
95*431ea2d0SNick Desaulniers         ++Overlap;
96*431ea2d0SNick Desaulniers     }
97*431ea2d0SNick Desaulniers }
98*431ea2d0SNick Desaulniers 
99*431ea2d0SNick Desaulniers } // namespace LIBC_NAMESPACE_DECL
100