1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/profiling/perf/unwind_queue.h"
18
19 #include "test/gtest_and_gmock.h"
20
21 namespace perfetto {
22 namespace profiling {
23 namespace {
24
TEST(UnwindQueueTest,SinglePass)25 TEST(UnwindQueueTest, SinglePass) {
26 static constexpr uint32_t kCapacity = 4;
27 UnwindQueue<int, kCapacity> queue;
28
29 // write kCapacity entries
30 for (int i = 0; i < static_cast<int>(kCapacity); i++) {
31 WriteView v = queue.BeginWrite();
32 ASSERT_TRUE(v.valid);
33 queue.at(v.write_pos) = i;
34 queue.CommitWrite();
35 }
36 {
37 // no more available capacity
38 WriteView v = queue.BeginWrite();
39 ASSERT_FALSE(v.valid);
40 }
41
42 // reader sees all four writes
43 ReadView v = queue.BeginRead();
44 ASSERT_EQ(v.read_pos, 0u);
45 ASSERT_EQ(v.write_pos, 4u);
46
47 std::vector<int> read_back;
48 for (auto pos = v.read_pos; pos < v.write_pos; pos++) {
49 read_back.push_back(queue.at(pos));
50 }
51 queue.CommitNewReadPosition(v.write_pos);
52
53 ASSERT_THAT(read_back, ::testing::ElementsAre(0, 1, 2, 3));
54
55 // writer sees an available slot
56 ASSERT_TRUE(queue.BeginWrite().valid);
57 // reader caught up
58 ASSERT_TRUE(queue.BeginRead().read_pos == queue.BeginRead().write_pos);
59 }
60
TEST(UnwindQueueTest,Wrapped)61 TEST(UnwindQueueTest, Wrapped) {
62 static constexpr uint32_t kCapacity = 4;
63 UnwindQueue<int, kCapacity> queue;
64
65 // write kCapacity entries
66 for (int i = 0; i < static_cast<int>(kCapacity); i++) {
67 WriteView v = queue.BeginWrite();
68 ASSERT_TRUE(v.valid);
69 queue.at(v.write_pos) = i;
70 queue.CommitWrite();
71 }
72
73 // no more available capacity
74 ASSERT_FALSE(queue.BeginWrite().valid);
75
76 {
77 // consume 2 entries (partial read)
78 ReadView v = queue.BeginRead();
79 ASSERT_EQ(v.read_pos, 0u);
80 ASSERT_EQ(v.write_pos, 4u);
81 queue.CommitNewReadPosition(v.read_pos + 2);
82 }
83
84 // write 2 more entries
85 for (int i = 0; i < 2; i++) {
86 WriteView v = queue.BeginWrite();
87 ASSERT_TRUE(v.valid);
88 queue.at(v.write_pos) = 4 + i;
89 queue.CommitWrite();
90 }
91
92 // no more available capacity
93 ASSERT_FALSE(queue.BeginWrite().valid);
94
95 // read the remainder of the buffer
96 ReadView v = queue.BeginRead();
97 ASSERT_EQ(v.read_pos, 2u);
98 ASSERT_EQ(v.write_pos, 6u);
99
100 std::vector<int> read_back;
101 for (auto pos = v.read_pos; pos < v.write_pos; pos++) {
102 read_back.push_back(queue.at(pos));
103 }
104 queue.CommitNewReadPosition(v.write_pos);
105
106 ASSERT_THAT(read_back, ::testing::ElementsAre(2, 3, 4, 5));
107
108 // writer sees an available slot
109 ASSERT_TRUE(queue.BeginWrite().valid);
110 // reader caught up
111 ASSERT_TRUE(queue.BeginRead().read_pos == queue.BeginRead().write_pos);
112 }
113
114 } // namespace
115 } // namespace profiling
116 } // namespace perfetto
117