xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/proto/proto_trace_reader_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2024 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/trace_processor/importers/proto/proto_trace_reader.h"
18 #include <memory>
19 
20 #include "perfetto/protozero/scattered_heap_buffer.h"
21 #include "protos/perfetto/common/builtin_clock.pbzero.h"
22 #include "src/trace_processor/importers/common/clock_tracker.h"
23 #include "src/trace_processor/importers/common/machine_tracker.h"
24 #include "src/trace_processor/storage/trace_storage.h"
25 
26 #include "test/gtest_and_gmock.h"
27 
28 #include "protos/perfetto/trace/clock_snapshot.pbzero.h"
29 #include "protos/perfetto/trace/remote_clock_sync.pbzero.h"
30 
31 namespace perfetto::trace_processor {
32 namespace {
33 
34 constexpr auto REALTIME = protos::pbzero::BUILTIN_CLOCK_REALTIME;
35 constexpr auto BOOTTIME = protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
36 
37 class ProtoTraceReaderTest : public ::testing::Test {
38  public:
ProtoTraceReaderTest()39   ProtoTraceReaderTest() {
40     context_.storage = std::make_unique<TraceStorage>();
41     context_.machine_tracker =
42         std::make_unique<MachineTracker>(&context_, 0x1001);
43     context_.clock_tracker = std::make_unique<ClockTracker>(&context_);
44     proto_trace_reader_ = std::make_unique<ProtoTraceReader>(&context_);
45   }
46 
Tokenize()47   util::Status Tokenize() {
48     trace_->Finalize();
49     std::vector<uint8_t> trace_bytes = trace_.SerializeAsArray();
50     std::unique_ptr<uint8_t[]> raw_trace(new uint8_t[trace_bytes.size()]);
51     memcpy(raw_trace.get(), trace_bytes.data(), trace_bytes.size());
52     auto status = proto_trace_reader_->Parse(TraceBlobView(
53         TraceBlob::TakeOwnership(std::move(raw_trace), trace_bytes.size())));
54 
55     trace_.Reset();
56     return status;
57   }
58 
59  protected:
60   protozero::HeapBuffered<protos::pbzero::Trace> trace_;
61   TraceProcessorContext context_;
62   std::unique_ptr<ProtoTraceReader> proto_trace_reader_;
63 };
64 
TEST_F(ProtoTraceReaderTest,RemoteClockSync_Valid)65 TEST_F(ProtoTraceReaderTest, RemoteClockSync_Valid) {
66   context_.machine_tracker =
67       std::make_unique<MachineTracker>(&context_, 0x1001);
68 
69   auto* packet = trace_->add_packet();
70   packet->set_machine_id(0x1001);
71   auto* remote_clock_sync = packet->set_remote_clock_sync();
72   auto* synced_clocks = remote_clock_sync->add_synced_clocks();
73   auto* client_clocks = synced_clocks->set_client_clocks();
74 
75   // First synced clock snapshots on both sides.
76   auto* clock = client_clocks->add_clocks();
77   clock->set_clock_id(BOOTTIME);
78   clock->set_timestamp(10000);
79 
80   auto* host_clocks = synced_clocks->set_host_clocks();
81   clock = host_clocks->add_clocks();
82   clock->set_clock_id(BOOTTIME);
83   clock->set_timestamp(120000);
84 
85   // Second synced clock snapshots on both sides.
86   synced_clocks = remote_clock_sync->add_synced_clocks();
87 
88   client_clocks = synced_clocks->set_client_clocks();
89   clock = client_clocks->add_clocks();
90   clock->set_clock_id(BOOTTIME);
91   clock->set_timestamp(25000);
92 
93   host_clocks = synced_clocks->set_host_clocks();
94   clock = host_clocks->add_clocks();
95   clock->set_clock_id(BOOTTIME);
96   clock->set_timestamp(135000);
97 
98   ASSERT_TRUE(Tokenize().ok());
99   ASSERT_EQ(1u, context_.clock_tracker->clock_offsets_for_testing().size());
100 }
101 
TEST_F(ProtoTraceReaderTest,RemoteClockSync_Incomplete)102 TEST_F(ProtoTraceReaderTest, RemoteClockSync_Incomplete) {
103   context_.machine_tracker =
104       std::make_unique<MachineTracker>(&context_, 0x1001);
105 
106   auto* packet = trace_->add_packet();
107   packet->set_machine_id(0x1001);
108   auto* remote_clock_sync = packet->set_remote_clock_sync();
109   auto* synced_clocks = remote_clock_sync->add_synced_clocks();
110   auto* client_clocks = synced_clocks->set_client_clocks();
111 
112   // First synced clock snapshots on both sides.
113   auto* clock = client_clocks->add_clocks();
114   clock->set_clock_id(BOOTTIME);
115   clock->set_timestamp(10000);
116 
117   auto* host_clocks = synced_clocks->set_host_clocks();
118   clock = host_clocks->add_clocks();
119   clock->set_clock_id(BOOTTIME);
120   clock->set_timestamp(120000);
121 
122   // Second synced clock snapshots on both sides.
123   synced_clocks = remote_clock_sync->add_synced_clocks();
124 
125   client_clocks = synced_clocks->set_client_clocks();
126   clock = client_clocks->add_clocks();
127   clock->set_clock_id(BOOTTIME);
128   clock->set_timestamp(25000);
129 
130   // Missing the second host CLOCK_BOOTTIME making it below the minimum
131   // requirement for using the remote_clock_sync for calculating clock offset.
132 
133   ASSERT_TRUE(Tokenize().ok());
134   // No valid clock offset.
135   ASSERT_EQ(0u, context_.clock_tracker->clock_offsets_for_testing().size());
136 }
137 
TEST_F(ProtoTraceReaderTest,CalculateClockOffset)138 TEST_F(ProtoTraceReaderTest, CalculateClockOffset) {
139   std::vector<ProtoTraceReader::SyncClockSnapshots> sync_clock_snapshots;
140   ProtoTraceReader::SyncClockSnapshots snapshots;
141   snapshots[BOOTTIME] = {120000, 10000};
142   snapshots[REALTIME] = {135000, 25000};
143   sync_clock_snapshots.push_back(std::move(snapshots));
144 
145   snapshots[BOOTTIME] = {140000, 20000};
146   snapshots[REALTIME] = {150000, 35000};
147   sync_clock_snapshots.push_back(std::move(snapshots));
148 
149   auto clock_offsets = proto_trace_reader_->CalculateClockOffsetsForTesting(
150       sync_clock_snapshots);
151   ASSERT_EQ(2u, clock_offsets.size());
152   // Client 10000      20000
153   // Host     120000     140000
154   // Estimated offsets: (10000 + 20000)/2 - 120000 = -105000,
155   //                    20000 - (120000 + 140000) / 2 = -110000.
156   // Average = -107500.
157   ASSERT_EQ(-107500, clock_offsets[BOOTTIME]);
158   // Client 25000      35000
159   // Host     135000     150000
160   // Estimated offsets: (25000 + 35000)/2 - 135000 = -105000,
161   //                    35000 - (135000 + 150000) / 2 = -107500.
162   // Average = -106250.
163   ASSERT_EQ(-106250, clock_offsets[REALTIME]);
164 }
165 
TEST_F(ProtoTraceReaderTest,CalculateClockOffset_AboveThreshold)166 TEST_F(ProtoTraceReaderTest, CalculateClockOffset_AboveThreshold) {
167   std::vector<ProtoTraceReader::SyncClockSnapshots> sync_clock_snapshots;
168   ProtoTraceReader::SyncClockSnapshots snapshots;
169   snapshots[BOOTTIME] = {120000, 10000};
170   snapshots[REALTIME] = {135000, 25000};
171   sync_clock_snapshots.push_back(std::move(snapshots));
172 
173   // 30 sec interval: the 2 clock snapshots will be considered 2 different
174   // rounds of clock synchronization IPC exchange and won't be used.
175   auto interval = 30ull * 1000 * 1000 * 1000;
176   snapshots[BOOTTIME] = {120000 + interval, 10000 + interval};
177   snapshots[REALTIME] = {135000 + interval, 25000 + interval};
178   sync_clock_snapshots.push_back(std::move(snapshots));
179 
180   auto clock_offsets = proto_trace_reader_->CalculateClockOffsetsForTesting(
181       sync_clock_snapshots);
182   ASSERT_EQ(0u, clock_offsets.size());
183 }
184 
TEST_F(ProtoTraceReaderTest,CalculateClockOffset_MultiRounds)185 TEST_F(ProtoTraceReaderTest, CalculateClockOffset_MultiRounds) {
186   std::vector<ProtoTraceReader::SyncClockSnapshots> sync_clock_snapshots;
187   ProtoTraceReader::SyncClockSnapshots snapshots;
188   // This emits clock offsets -105000, -110000.
189   snapshots[BOOTTIME] = {120000, 10000};
190   sync_clock_snapshots.push_back(std::move(snapshots));
191   snapshots[BOOTTIME] = {140000, 20000};
192   sync_clock_snapshots.push_back(std::move(snapshots));
193 
194   // The interval works as a delimeter of IPC exchange.
195   auto interval = 30ull * 1000 * 1000 * 1000;
196 
197   // This emits clock offsets: (30000 + 45000) / 2 - 160000 = -122500,
198   //                           45000 - (160000 + 170000) / 2 = -120000.
199   snapshots[BOOTTIME] = {160000 + interval, 30000 + interval};
200   sync_clock_snapshots.push_back(std::move(snapshots));
201   snapshots[BOOTTIME] = {170000 + interval, 45000 + interval};
202   sync_clock_snapshots.push_back(std::move(snapshots));
203 
204   auto clock_offsets = proto_trace_reader_->CalculateClockOffsetsForTesting(
205       sync_clock_snapshots);
206   ASSERT_EQ(1u, clock_offsets.size());
207   // Average(-105000, -110000, -122500, -120000) = -114375.
208   ASSERT_EQ(-114375, clock_offsets[BOOTTIME]);
209 }
210 
211 }  // namespace
212 }  // namespace perfetto::trace_processor
213