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