11 #include "gmock/gmock.h"
12 #include "gtest/gtest-message.h"
13 #include "gtest/gtest.h"
15 namespace memory_unittest {
21 void *builtin_memcpy_wrapper(
void *dest,
const void *src,
size_t count) {
22 return __builtin_memcpy(dest, src, count);
25 int builtin_memcmp_wrapper(
const void *lhs,
const void *rhs,
size_t count) {
26 return __builtin_memcmp(lhs, rhs, count);
29 void *builtin_memset_wrapper(
void *dest,
int ch,
size_t count) {
30 return __builtin_memset(dest, ch, count);
41 int ref_memrcmp(
const void *lhs,
const void *rhs,
size_t len) {
42 const uint8_t *lhs8 = (uint8_t *)lhs;
43 const uint8_t *rhs8 = (uint8_t *)rhs;
45 for (
size_t i = 0; i < len; ++i) {
47 if (lhs8[j] < rhs8[j]) {
49 }
else if (lhs8[j] > rhs8[j]) {
56 void *ref_memchr(
const void *ptr,
int value,
size_t len) {
57 uint8_t *ptr8 = (uint8_t *)ptr;
58 uint8_t value8 = (uint8_t)value;
59 for (
size_t i = 0; i < len; ++i) {
60 if (ptr8[i] == value8) {
67 void *ref_memrchr(
const void *ptr,
int value,
size_t len) {
68 uint8_t *ptr8 = (uint8_t *)ptr;
69 uint8_t value8 = (uint8_t)value;
70 for (
size_t i = 0; i < len; ++i) {
71 size_t idx = len - i - 1;
72 if (ptr8[idx] == value8) {
83 class MemCpyTest :
public ::testing::TestWithParam<decltype(&ot_memcpy)> {};
84 class MemCmpTest :
public ::testing::TestWithParam<decltype(&ot_memcmp)> {};
85 class MemSetTest :
public ::testing::TestWithParam<decltype(&ot_memset)> {};
86 class MemChrTest :
public ::testing::TestWithParam<decltype(&ot_memchr)> {};
89 ::testing::Values(ot_memcpy, builtin_memcpy_wrapper));
91 ::testing::Values(ot_memcmp, builtin_memcmp_wrapper,
94 ::testing::Values(ot_memset, builtin_memset_wrapper));
96 ::testing::Values(ot_memchr, ref_memchr, ot_memrchr,
99 using ::testing::Each;
100 using ::testing::ElementsAre;
103 auto memcpy_func = GetParam();
105 static constexpr
size_t kLen = 8;
106 std::vector<uint32_t> xs = {1, 2, 3, 4, 5, 6, 7, 8};
107 std::vector<uint32_t> ys(kLen);
108 ASSERT_EQ(xs.size(), kLen);
111 memcpy_func(ys.data() + 1, xs.data(), (kLen - 1) *
sizeof(uint32_t));
112 EXPECT_THAT(ys, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7));
115 memcpy_func(ys.data(), xs.data(), (kLen - 1) *
sizeof(uint32_t));
116 EXPECT_THAT(ys, ElementsAre(1, 2, 3, 4, 5, 6, 7, 7));
119 memcpy_func(&ys[2], xs.data(), (kLen - 2) *
sizeof(uint32_t));
120 EXPECT_THAT(ys, ElementsAre(1, 2, 1, 2, 3, 4, 5, 6));
123 TEST_P(MemCpyTest, VaryingSize) {
124 auto memcpy_func = GetParam();
126 static constexpr
size_t kLen = 8;
127 static constexpr uint32_t kZeroes[kLen] = {0};
128 std::vector<uint32_t> xs = {1, 2, 3, 4, 5, 6, 7, 8};
129 ASSERT_EQ(xs.size(), kLen);
131 for (
size_t i = 0; i < kLen; ++i) {
133 memcpy_func(xs.data(), kZeroes, i *
sizeof(uint32_t));
135 std::vector<uint32_t> expected = {1, 2, 3, 4, 5, 6, 7, 8};
136 std::fill_n(expected.begin(), i, 0);
137 EXPECT_EQ(xs, expected) <<
"i=" << i;
141 TEST_P(MemCpyTest, VarySrcAlignment) {
142 auto memcpy_func = GetParam();
144 static constexpr
size_t kLen = 8;
145 const std::vector<uint32_t> xs_original = {1, 2, 3, 4, 5, 6, 7, 8};
146 ASSERT_EQ(xs_original.size(), kLen);
148 const std::vector<uint32_t> ys = {11, 12, 13, 14, 15, 16, 17, 18};
149 ASSERT_EQ(ys.size(), kLen);
151 for (
size_t i = 0; i < kLen; ++i) {
152 SCOPED_TRACE(testing::Message() <<
"i=" << i);
154 std::vector<uint32_t> xs(xs_original);
157 const size_t num_u32_to_copy = kLen - i;
158 memcpy_func(xs.data(), &ys[i], num_u32_to_copy *
sizeof(uint32_t));
160 std::vector<uint32_t> xs_expected(xs_original);
161 for (
size_t j = 0; j < num_u32_to_copy; ++j) {
162 xs_expected[j] = 11 + i + j;
164 EXPECT_EQ(xs, xs_expected);
168 TEST_P(MemCpyTest, VaryDestAlignment) {
169 auto memcpy_func = GetParam();
171 static constexpr
size_t kLen = 8;
172 const std::vector<uint32_t> xs_original = {1, 2, 3, 4, 5, 6, 7, 8};
173 ASSERT_EQ(xs_original.size(), kLen);
175 const std::vector<uint32_t> ys = {11, 12, 13, 14, 15, 16, 17, 18};
176 ASSERT_EQ(ys.size(), kLen);
178 for (
size_t i = 0; i < kLen; ++i) {
179 SCOPED_TRACE(testing::Message() <<
"i=" << i);
181 std::vector<uint32_t> xs(xs_original);
184 const size_t num_u32_to_copy = kLen - i;
185 memcpy_func(&xs[i], ys.data(), num_u32_to_copy *
sizeof(uint32_t));
187 std::vector<uint32_t> xs_expected(xs_original);
188 for (
size_t j = 0; j < num_u32_to_copy; ++j) {
189 xs_expected[j + i] = 11 + j;
192 EXPECT_EQ(xs, xs_expected);
196 TEST_P(MemCmpTest, NullParam) {
197 auto memcmp_func = GetParam();
199 const uint8_t data[16] = {0};
200 EXPECT_EQ(memcmp_func(
nullptr,
nullptr, 0), 0);
201 EXPECT_EQ(memcmp_func(data,
nullptr, 0), 0);
202 EXPECT_EQ(memcmp_func(
nullptr, data, 0), 0);
203 EXPECT_EQ(memcmp_func(data, data, 0), 0);
206 TEST_P(MemCmpTest, ZeroesVaryingOffsetsAndLengths) {
207 auto memcmp_func = GetParam();
209 const uint8_t data[16] = {0};
210 for (
size_t offset = 0; offset <= 8; offset++) {
211 for (
size_t len = 0; len < 8; len++) {
212 EXPECT_EQ(memcmp_func(data, data, len), 0);
213 EXPECT_EQ(memcmp_func(data, data + offset, len), 0);
214 EXPECT_EQ(memcmp_func(data + offset, data, len), 0);
215 EXPECT_EQ(memcmp_func(data + offset, data + offset, len), 0);
220 TEST_P(MemSetTest, Null) {
221 auto memset_func = GetParam();
223 EXPECT_EQ(memset_func(
nullptr, 0, 0),
nullptr);
226 TEST_P(MemCmpTest, Properties) {
227 auto memcmp_func = GetParam();
229 constexpr
size_t kLen = 5;
230 constexpr uint8_t xs[kLen] = {0, 0, 0, 0, 0};
231 constexpr uint8_t ys[kLen] = {0, 0, 0, 1, 3};
232 constexpr uint8_t zs[kLen] = {0, 0, 0, 1, 4};
235 EXPECT_EQ(memcmp_func(xs, xs, kLen), 0);
236 EXPECT_EQ(memcmp_func(ys, ys, kLen), 0);
237 EXPECT_EQ(memcmp_func(zs, zs, kLen), 0);
239 EXPECT_LT(memcmp_func(xs, ys, kLen), 0);
240 EXPECT_LT(memcmp_func(ys, zs, kLen), 0);
241 EXPECT_LT(memcmp_func(xs, zs, kLen), 0);
243 EXPECT_GT(memcmp_func(ys, xs, kLen), 0);
244 EXPECT_GT(memcmp_func(zs, ys, kLen), 0);
245 EXPECT_GT(memcmp_func(zs, xs, kLen), 0);
248 TEST_P(MemCmpTest, DoesNotUseSystemEndianness) {
249 auto memcmp_func = GetParam();
251 const bool reverse = memcmp_func == &
memrcmp || memcmp_func == &ref_memrcmp;
253 constexpr uint8_t kBuf1[] = {0, 0, 0, 1};
254 constexpr uint8_t kBuf2[] = {0, 0, 1, 0};
261 EXPECT_LT(memcmp_func(kBuf1, kBuf2,
sizeof(kBuf1)), 0);
263 EXPECT_GT(memcmp_func(kBuf1, kBuf2,
sizeof(kBuf1)), 0);
267 TEST_P(MemSetTest, Simple) {
268 auto memset_func = GetParam();
270 for (uint32_t len = 0; len < 32; ++len) {
271 SCOPED_TRACE(testing::Message() <<
"len = " << len);
273 std::vector<uint32_t> xs(len, 123);
274 EXPECT_THAT(xs, Each(123));
275 EXPECT_EQ(memset_func(xs.data(), 0, xs.size() *
sizeof(uint32_t)),
277 EXPECT_THAT(xs, Each(0));
281 TEST_P(MemChrTest, Null) {
282 auto memchr_func = GetParam();
284 EXPECT_EQ(memchr_func(
nullptr, 0, 0),
nullptr);
285 EXPECT_EQ(memchr_func(
nullptr, 42, 0),
nullptr);
288 TEST_P(MemChrTest, NonNullButEmpty) {
289 auto memchr_func = GetParam();
291 const uint8_t kEmpty[] = {};
292 static_assert(
sizeof(kEmpty) == 0,
"kEmpty should contain zero bytes");
294 EXPECT_EQ(memchr_func(kEmpty, 0,
sizeof(kEmpty)),
nullptr);
295 EXPECT_EQ(memchr_func(kEmpty, 42,
sizeof(kEmpty)),
nullptr);
298 TEST_P(MemChrTest, Simple) {
299 auto memchr_func = GetParam();
301 std::vector<uint8_t> vec = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
302 EXPECT_EQ(memchr_func(vec.data(), 0, vec.size()), vec.data());
303 EXPECT_EQ(memchr_func(vec.data(), 5, vec.size()), vec.data() + 5);
305 constexpr
size_t kLen = 11;
306 constexpr uint8_t data[kLen] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
307 EXPECT_EQ(memchr_func(data, 0, kLen), data);
308 EXPECT_EQ(memchr_func(data, 1, kLen), data + 1);
309 EXPECT_EQ(memchr_func(data, 4, kLen), data + 4);
310 EXPECT_EQ(memchr_func(data, 8, kLen), data + 8);
311 EXPECT_EQ(memchr_func(data, 42, kLen),
nullptr);
314 TEST_P(MemChrTest, VaryingLengths) {
315 auto memchr_func = GetParam();
317 for (
size_t len = 0; len < 16; ++len) {
318 std::vector<uint8_t> vec;
320 for (
size_t i = 0; i < len; ++i) {
321 vec.push_back(
static_cast<uint8_t
>(i));
324 for (
size_t i = 0; i < len; ++i) {
325 EXPECT_EQ(memchr_func(vec.data(), i, len), vec.data() + i);
328 EXPECT_EQ(memchr_func(vec.data(), len + 1, len),
nullptr);
332 TEST_P(MemChrTest, RepeatedBytes) {
333 auto memchr_func = GetParam();
336 memchr_func == &ot_memrchr || memchr_func == &ref_memrchr;
339 constexpr uint8_t kBuf[] = {
354 EXPECT_EQ(memchr_func(kBuf, 0,
sizeof(kBuf)), kBuf);
355 EXPECT_EQ(memchr_func(kBuf, 1,
sizeof(kBuf)), kBuf + 1);
356 EXPECT_EQ(memchr_func(kBuf, 2,
sizeof(kBuf)), kBuf + 2);
357 EXPECT_EQ(memchr_func(kBuf, 3,
sizeof(kBuf)), kBuf + 3);
358 EXPECT_EQ(memchr_func(kBuf, 4,
sizeof(kBuf)), reverse ? kBuf + 5 : kBuf + 4);
359 EXPECT_EQ(memchr_func(kBuf, 5,
sizeof(kBuf)), kBuf + 6);
360 EXPECT_EQ(memchr_func(kBuf, 6,
sizeof(kBuf)), kBuf + 7);
361 EXPECT_EQ(memchr_func(kBuf, 7,
sizeof(kBuf)), kBuf + 8);
362 EXPECT_EQ(memchr_func(kBuf, 8,
sizeof(kBuf)), reverse ? kBuf + 10 : kBuf + 9);
363 EXPECT_EQ(memchr_func(kBuf, 9,
sizeof(kBuf)), kBuf + 11);
364 EXPECT_EQ(memchr_func(kBuf, 10,
sizeof(kBuf)), kBuf + 12);
365 EXPECT_EQ(memchr_func(kBuf, 11,
sizeof(kBuf)), kBuf + 13);
366 EXPECT_EQ(memchr_func(kBuf, 12,
sizeof(kBuf)),
367 reverse ? kBuf + 15 : kBuf + 14);
368 EXPECT_EQ(memchr_func(kBuf, 13,
sizeof(kBuf)),
369 reverse ? kBuf + 18 : kBuf + 16);
370 EXPECT_EQ(memchr_func(kBuf, 14,
sizeof(kBuf)), kBuf + 19);
371 EXPECT_EQ(memchr_func(kBuf, 15,
sizeof(kBuf)), kBuf + 20);
372 EXPECT_EQ(memchr_func(kBuf, 16,
sizeof(kBuf)),
373 reverse ? kBuf + 23 : kBuf + 21);
374 EXPECT_EQ(memchr_func(kBuf, 17,
sizeof(kBuf)),
375 reverse ? kBuf + 27 : kBuf + 24);