blob: 2afa68ab68a72da7000814e1933d15203b94867e [file] [log] [blame]
Vishnu Nair7891e962021-11-11 12:07:21 -08001/*
2 * Copyright 2021 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 <gmock/gmock.h>
18#include <gtest/gtest.h>
19
20#include <gui/SurfaceComposerClient.h>
21
22#include "Tracing/RingBuffer.h"
23#include "Tracing/TransactionTracing.h"
24
25using namespace android::surfaceflinger;
26
27namespace android {
28
29class TransactionTracingTest : public testing::Test {
30protected:
31 std::unique_ptr<android::TransactionTracing> mTracing;
32
33 void SetUp() override { mTracing = std::make_unique<android::TransactionTracing>(); }
34
35 void TearDown() override { mTracing.reset(); }
36
37 auto getCommittedTransactions() {
38 std::scoped_lock<std::mutex> lock(mTracing->mMainThreadLock);
39 return mTracing->mCommittedTransactions;
40 }
41
42 auto getQueuedTransactions() {
43 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
44 return mTracing->mQueuedTransactions;
45 }
46
47 auto getUsedBufferSize() {
48 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
49 return mTracing->mBuffer->used();
50 }
51
52 auto flush() { return mTracing->flush(); }
53
54 auto bufferFront() {
55 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
56 return mTracing->mBuffer->front();
57 }
58
59 bool threadIsJoinable() {
60 std::scoped_lock lock(mTracing->mMainThreadLock);
61 return mTracing->mThread.joinable();
62 }
63
64 std::string writeToString() {
65 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
66 std::string output;
67 proto::TransactionTraceFile fileProto = mTracing->createTraceFileProto();
68 mTracing->mBuffer->writeToString(fileProto, &output);
69 return output;
70 }
71
72 // Test that we clean up the tracing thread and free any memory allocated.
73 void verifyDisabledTracingState() {
74 EXPECT_FALSE(mTracing->isEnabled());
75 EXPECT_FALSE(threadIsJoinable());
76 EXPECT_EQ(getCommittedTransactions().size(), 0u);
77 EXPECT_EQ(getQueuedTransactions().size(), 0u);
78 EXPECT_EQ(getUsedBufferSize(), 0u);
79 }
80
81 void verifyEntry(const proto::TransactionTraceEntry& actualProto,
82 const std::vector<TransactionState> expectedTransactions,
83 int64_t expectedVsyncId) {
84 EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
85 EXPECT_EQ(actualProto.transactions().size(),
86 static_cast<int32_t>(expectedTransactions.size()));
87 for (uint32_t i = 0; i < expectedTransactions.size(); i++) {
88 EXPECT_EQ(actualProto.transactions(static_cast<int32_t>(i)).pid(),
89 expectedTransactions[i].originPid);
90 }
91 }
92};
93
94TEST_F(TransactionTracingTest, enable) {
95 EXPECT_FALSE(mTracing->isEnabled());
96 mTracing->enable();
97 EXPECT_TRUE(mTracing->isEnabled());
98 mTracing->disable();
99 verifyDisabledTracingState();
100}
101
102TEST_F(TransactionTracingTest, addTransactions) {
103 mTracing->enable();
104 std::vector<TransactionState> transactions;
105 transactions.reserve(100);
106 for (uint64_t i = 0; i < 100; i++) {
107 TransactionState transaction;
108 transaction.id = i;
109 transaction.originPid = static_cast<int32_t>(i);
110 transactions.emplace_back(transaction);
111 mTracing->addQueuedTransaction(transaction);
112 }
113
114 // Split incoming transactions into two and commit them in reverse order to test out of order
115 // commits.
116 std::vector<TransactionState> firstTransactionSet =
117 std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
118 int64_t firstTransactionSetVsyncId = 42;
119 mTracing->addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId);
120
121 int64_t secondTransactionSetVsyncId = 43;
122 std::vector<TransactionState> secondTransactionSet =
123 std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50);
124 mTracing->addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId);
125 flush();
126
127 std::string protoString = writeToString();
128 proto::TransactionTraceFile proto;
129 proto.ParseFromString(protoString);
130 EXPECT_EQ(proto.entry().size(), 2);
131 verifyEntry(proto.entry(0), firstTransactionSet, firstTransactionSetVsyncId);
132 verifyEntry(proto.entry(1), secondTransactionSet, secondTransactionSetVsyncId);
133
134 mTracing->disable();
135 verifyDisabledTracingState();
136}
137
138} // namespace android