| 1 | //===-- sanitizer_vector_test.cpp -----------------------------------------===// |
| 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 | // This file is a part of *Sanitizer runtime. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | #include "sanitizer_common/sanitizer_ring_buffer.h" |
| 13 | #include "gtest/gtest.h" |
| 14 | |
| 15 | namespace __sanitizer { |
| 16 | |
| 17 | struct LargeStruct { |
| 18 | int64_t v; |
| 19 | int64_t [3]; |
| 20 | |
| 21 | explicit LargeStruct(int64_t v) : v(v) {} |
| 22 | operator int64_t() { return v; } |
| 23 | }; |
| 24 | |
| 25 | struct Struct10Bytes { |
| 26 | short t[3]; |
| 27 | }; |
| 28 | |
| 29 | TEST(RingBuffer, Construct) { |
| 30 | RingBuffer<int64_t> *RBlong = RingBuffer<int64_t>::New(20); |
| 31 | EXPECT_EQ(RBlong->size(), 20U); |
| 32 | RBlong->Delete(); |
| 33 | } |
| 34 | |
| 35 | template <class T> void TestRB() { |
| 36 | RingBuffer<T> *RB; |
| 37 | const size_t Sizes[] = {1, 2, 3, 5, 8, 16, 20, 40, 10000}; |
| 38 | for (size_t Size : Sizes) { |
| 39 | RB = RingBuffer<T>::New(Size); |
| 40 | EXPECT_EQ(RB->size(), Size); |
| 41 | RB->Delete(); |
| 42 | } |
| 43 | |
| 44 | RB = RingBuffer<T>::New(4); |
| 45 | EXPECT_EQ(RB->size(), 4U); |
| 46 | #define EXPECT_RING_BUFFER(a0, a1, a2, a3) \ |
| 47 | EXPECT_EQ((int64_t)(*RB)[0], (int64_t)a0); \ |
| 48 | EXPECT_EQ((int64_t)(*RB)[1], (int64_t)a1); \ |
| 49 | EXPECT_EQ((int64_t)(*RB)[2], (int64_t)a2); \ |
| 50 | EXPECT_EQ((int64_t)(*RB)[3], (int64_t)a3); |
| 51 | |
| 52 | RB->push(T(1)); EXPECT_RING_BUFFER(1, 0, 0, 0); |
| 53 | RB->push(T(2)); EXPECT_RING_BUFFER(2, 1, 0, 0); |
| 54 | RB->push(T(3)); EXPECT_RING_BUFFER(3, 2, 1, 0); |
| 55 | RB->push(T(4)); EXPECT_RING_BUFFER(4, 3, 2, 1); |
| 56 | RB->push(T(5)); EXPECT_RING_BUFFER(5, 4, 3, 2); |
| 57 | RB->push(T(6)); EXPECT_RING_BUFFER(6, 5, 4, 3); |
| 58 | RB->push(T(7)); EXPECT_RING_BUFFER(7, 6, 5, 4); |
| 59 | RB->push(T(8)); EXPECT_RING_BUFFER(8, 7, 6, 5); |
| 60 | RB->push(T(9)); EXPECT_RING_BUFFER(9, 8, 7, 6); |
| 61 | RB->push(T(10)); EXPECT_RING_BUFFER(10, 9, 8, 7); |
| 62 | RB->push(T(11)); EXPECT_RING_BUFFER(11, 10, 9, 8); |
| 63 | RB->push(T(12)); EXPECT_RING_BUFFER(12, 11, 10, 9); |
| 64 | |
| 65 | #undef EXPECT_RING_BUFFER |
| 66 | } |
| 67 | |
| 68 | #if SANITIZER_WORDSIZE == 64 |
| 69 | TEST(RingBuffer, int64) { |
| 70 | TestRB<int64_t>(); |
| 71 | } |
| 72 | |
| 73 | TEST(RingBuffer, LargeStruct) { |
| 74 | TestRB<LargeStruct>(); |
| 75 | } |
| 76 | |
| 77 | template<typename T> |
| 78 | CompactRingBuffer<T> *AllocCompactRingBuffer(size_t count) { |
| 79 | size_t sz = sizeof(T) * count; |
| 80 | EXPECT_EQ(0ULL, sz % 4096); |
| 81 | void *p = MmapAlignedOrDieOnFatalError(sz, sz * 2, "CompactRingBuffer" ); |
| 82 | return new CompactRingBuffer<T>(p, sz); |
| 83 | } |
| 84 | |
| 85 | TEST(CompactRingBuffer, int64) { |
| 86 | const size_t page_sizes[] = {1, 2, 4, 128}; |
| 87 | |
| 88 | for (size_t pages : page_sizes) { |
| 89 | size_t count = 4096 * pages / sizeof(int64_t); |
| 90 | auto R = AllocCompactRingBuffer<int64_t>(count); |
| 91 | int64_t top = count * 3 + 13; |
| 92 | for (int64_t i = 0; i < top; ++i) R->push(i); |
| 93 | for (int64_t i = 0; i < (int64_t)count; ++i) |
| 94 | EXPECT_EQ(top - i - 1, (*R)[i]); |
| 95 | } |
| 96 | } |
| 97 | #endif |
| 98 | } // namespace __sanitizer |
| 99 | |