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 | |