Expand Up
@@ -8,64 +8,106 @@
#include " src/__support/CPP/ArrayRef.h"
#include " src/string/memmove.h"
#include " utils/UnitTest/MemoryMatcher.h"
#include " utils/UnitTest/Test.h"
class LlvmLibcMemmoveTest : public __llvm_libc ::testing::Test {
public:
void check_memmove (void *dst, const void *src, size_t count,
const unsigned char *str,
const __llvm_libc::cpp::ArrayRef<unsigned char > expected) {
void *result = __llvm_libc::memmove (dst, src, count);
// Making sure the pointer returned is same with `dst`.
EXPECT_EQ (result, dst);
// `expected` is designed according to `str`.
// `dst` and `src` might be part of `str`.
// Making sure `str` is same with `expected`.
for (size_t i = 0 ; i < expected.size (); ++i)
EXPECT_EQ (str[i], expected[i]);
}
};
using __llvm_libc::cpp::Array;
using __llvm_libc::cpp::ArrayRef;
using __llvm_libc::cpp::MutableArrayRef;
TEST_F (LlvmLibcMemmoveTest, MoveZeroByte) {
unsigned char dst[] = {' a' , ' b' };
const unsigned char src[] = {' y' , ' z' };
const unsigned char expected[] = {' a' , ' b' };
check_memmove (dst, src, 0 , dst, expected);
TEST (LlvmLibcMemmoveTest, MoveZeroByte) {
char Buffer[] = {' a' , ' b' , ' y' , ' z' };
const char Expected[] = {' a' , ' b' , ' y' , ' z' };
void *const Dst = Buffer;
void *const Ret = __llvm_libc::memmove (Dst, Buffer + 2 , 0 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
TEST_F (LlvmLibcMemmoveTest, OverlapThatDstAndSrcPointToSameAddress) {
unsigned char str[] = {' a' , ' b' };
const unsigned char expected[] = {' a' , ' b' };
check_memmove (str, str, 1 , str, expected);
TEST (LlvmLibcMemmoveTest, DstAndSrcPointToSameAddress) {
char Buffer[] = {' a' , ' b' };
const char Expected[] = {' a' , ' b' };
void *const Dst = Buffer;
void *const Ret = __llvm_libc::memmove (Dst, Buffer, 1 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
TEST_F (LlvmLibcMemmoveTest, OverlapThatDstStartsBeforeSrc ) {
TEST (LlvmLibcMemmoveTest, DstStartsBeforeSrc ) {
// Set boundary at beginning and end for not overstepping when
// copy forward or backward.
unsigned char str[] = {' z' , ' a' , ' b' , ' c' , ' z' };
const unsigned char expected[] = {' z' , ' b' , ' c' , ' c' , ' z' };
// `dst` is `&str[1]`.
check_memmove (&str[1 ], &str[2 ], 2 , str, expected);
char Buffer[] = {' z' , ' a' , ' b' , ' c' , ' z' };
const char Expected[] = {' z' , ' b' , ' c' , ' c' , ' z' };
void *const Dst = Buffer + 1 ;
void *const Ret = __llvm_libc::memmove (Dst, Buffer + 2 , 2 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
TEST_F (LlvmLibcMemmoveTest, OverlapThatDstStartsAfterSrc) {
unsigned char str[] = {' z' , ' a' , ' b' , ' c' , ' z' };
const unsigned char expected[] = {' z' , ' a' , ' a' , ' b' , ' z' };
check_memmove (&str[2 ], &str[1 ], 2 , str, expected);
TEST (LlvmLibcMemmoveTest, DstStartsAfterSrc) {
char Buffer[] = {' z' , ' a' , ' b' , ' c' , ' z' };
const char Expected[] = {' z' , ' a' , ' a' , ' b' , ' z' };
void *const Dst = Buffer + 2 ;
void *const Ret = __llvm_libc::memmove (Dst, Buffer + 1 , 2 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
// e.g. `dst ` follow `src`.
// e.g. `Dst ` follow `src`.
// str: [abcdefghij]
// [__src_____]
// [_____dst__]
TEST_F (LlvmLibcMemmoveTest, SrcFollowDst) {
unsigned char str[] = {' z' , ' a' , ' b' , ' z' };
const unsigned char expected[] = {' z' , ' b' , ' b' , ' z' };
check_memmove (&str[1 ], &str[2 ], 1 , str, expected);
// [_____Dst__]
TEST (LlvmLibcMemmoveTest, SrcFollowDst) {
char Buffer[] = {' z' , ' a' , ' b' , ' z' };
const char Expected[] = {' z' , ' b' , ' b' , ' z' };
void *const Dst = Buffer + 1 ;
void *const Ret = __llvm_libc::memmove (Dst, Buffer + 2 , 1 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
TEST (LlvmLibcMemmoveTest, DstFollowSrc) {
char Buffer[] = {' z' , ' a' , ' b' , ' z' };
const char Expected[] = {' z' , ' a' , ' a' , ' z' };
void *const Dst = Buffer + 2 ;
void *const Ret = __llvm_libc::memmove (Dst, Buffer + 1 , 1 );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
TEST_F (LlvmLibcMemmoveTest, DstFollowSrc) {
unsigned char str[] = {' z' , ' a' , ' b' , ' z' };
const unsigned char expected[] = {' z' , ' a' , ' a' , ' z' };
check_memmove (&str[2 ], &str[1 ], 1 , str, expected);
static constexpr int kMaxSize = 512 ;
char GetRandomChar () {
static constexpr const uint64_t A = 1103515245 ;
static constexpr const uint64_t C = 12345 ;
static constexpr const uint64_t M = 1ULL << 31 ;
static uint64_t Seed = 123456789 ;
Seed = (A * Seed + C) % M;
return Seed;
}
void Randomize (MutableArrayRef<char > Buffer) {
for (auto ¤t : Buffer)
current = GetRandomChar ();
}
TEST (LlvmLibcMemmoveTest, Thorough) {
using LargeBuffer = Array<char , 3 * kMaxSize >;
LargeBuffer GroundTruth;
Randomize (GroundTruth);
for (int Size = 0 ; Size < kMaxSize ; ++Size ) {
for (int Offset = -Size ; Offset < Size ; ++Offset) {
LargeBuffer Buffer = GroundTruth;
LargeBuffer Expected = GroundTruth;
size_t DstOffset = kMaxSize ;
size_t SrcOffset = kMaxSize + Offset;
for (int I = 0 ; I < Size ; ++I)
Expected[DstOffset + I] = GroundTruth[SrcOffset + I];
void *const Dst = Buffer.data () + DstOffset;
void *const Ret =
__llvm_libc::memmove (Dst, Buffer.data () + SrcOffset, Size );
EXPECT_EQ (Ret, Dst);
EXPECT_MEM_EQ (Buffer, Expected);
}
}
}