1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <common/include/CommandHandlerFunctor.hpp>
7 #include <common/include/CommonProfilingUtils.hpp>
8 #include <common/include/Threads.hpp>
9 #include <server/include/timelineDecoder/TimelineCaptureCommandHandler.hpp>
10 #include <server/include/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp>
11 #include <server/include/timelineDecoder/TimelineDecoder.hpp>
12
13 #include <client/src/BufferManager.hpp>
14 #include <client/src/ProfilingService.hpp>
15 #include <client/src/PacketBuffer.hpp>
16 #include <client/src/TimelinePacketWriterFactory.hpp>
17
18 #include <doctest/doctest.h>
19
20 TEST_SUITE("TimelineDecoderTests")
21 {
SendTimelinePacketToCommandHandler(const unsigned char * packetBuffer,arm::pipe::CommandHandlerFunctor & CommandHandler)22 void SendTimelinePacketToCommandHandler(const unsigned char* packetBuffer,
23 arm::pipe::CommandHandlerFunctor& CommandHandler)
24 {
25 uint32_t uint32_t_size = sizeof(uint32_t);
26 unsigned int offset = 0;
27
28 uint32_t header[2];
29 header[0] = arm::pipe::ReadUint32(packetBuffer, offset);
30 offset += uint32_t_size;
31 header[1] = arm::pipe::ReadUint32(packetBuffer, offset);
32 offset += uint32_t_size;
33 uint32_t PacketDataLength = header[1] & 0x00FFFFFF;
34
35 auto uniquePacketData = std::make_unique<unsigned char[]>(PacketDataLength);
36 std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength);
37
38 arm::pipe::Packet packet(header[0], PacketDataLength, uniquePacketData);
39
40 CHECK(std::memcmp(packetBuffer + offset, packet.GetData(), packet.GetLength()) == 0);
41
42 CommandHandler(packet);
43 }
44
PushEntity(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Entity entity)45 void PushEntity(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Entity entity)
46 {
47 model.m_Entities.emplace_back(entity);
48 }
49
PushEventClass(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::EventClass eventClass)50 void PushEventClass(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::EventClass eventClass)
51 {
52 model.m_EventClasses.emplace_back(eventClass);
53 }
54
PushEvent(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Event event)55 void PushEvent(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Event event)
56 {
57 model.m_Events.emplace_back(event);
58 }
59
PushLabel(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Label label)60 void PushLabel(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Label label)
61 {
62 model.m_Labels.emplace_back(label);
63 }
64
PushRelationship(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Relationship relationship)65 void PushRelationship(arm::pipe::TimelineDecoder::Model& model,
66 const arm::pipe::ITimelineDecoder::Relationship relationship)
67 {
68 model.m_Relationships.emplace_back(relationship);
69 }
70
71 TEST_CASE("TimelineDirectoryTest")
72 {
73 uint32_t uint8_t_size = sizeof(uint8_t);
74 uint32_t uint32_t_size = sizeof(uint32_t);
75 uint32_t uint64_t_size = sizeof(uint64_t);
76
77 arm::pipe::BufferManager bufferManager(5);
78 arm::pipe::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
79
80 std::unique_ptr<arm::pipe::ISendTimelinePacket> sendTimelinePacket =
81 timelinePacketWriterFactory.GetSendTimelinePacket();
82
83 arm::pipe::PacketVersionResolver packetVersionResolver;
84
85 arm::pipe::TimelineDecoder timelineDecoder;
86 arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
87 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder);
88
89 arm::pipe::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler(
90 1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(),
91 timelineCaptureCommandHandler, true);
92
93 sendTimelinePacket->SendTimelineMessageDirectoryPackage();
94 sendTimelinePacket->Commit();
95
96 std::vector<arm::pipe::SwTraceMessage> swTraceBufferMessages;
97
98 unsigned int offset = uint32_t_size * 2;
99
100 std::unique_ptr<arm::pipe::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer();
101
102 uint8_t readStreamVersion = ReadUint8(packetBuffer, offset);
103 CHECK(readStreamVersion == 4);
104 offset += uint8_t_size;
105 uint8_t readPointerBytes = ReadUint8(packetBuffer, offset);
106 CHECK(readPointerBytes == uint64_t_size);
107 offset += uint8_t_size;
108 uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset);
109 CHECK(readThreadIdBytes == arm::pipe::ThreadIdSize);
110 offset += uint8_t_size;
111
112 uint32_t declarationSize = arm::pipe::ReadUint32(packetBuffer->GetReadableData(), offset);
113 offset += uint32_t_size;
114 for(uint32_t i = 0; i < declarationSize; ++i)
115 {
116 swTraceBufferMessages.push_back(arm::pipe::ReadSwTraceMessage(packetBuffer->GetReadableData(),
117 offset,
118 packetBuffer->GetSize()));
119 }
120
121 SendTimelinePacketToCommandHandler(packetBuffer->GetReadableData(), timelineDirectoryCaptureCommandHandler);
122
123 for(uint32_t index = 0; index < declarationSize; ++index)
124 {
125 arm::pipe::SwTraceMessage& bufferMessage = swTraceBufferMessages[index];
126 arm::pipe::SwTraceMessage& handlerMessage = timelineDirectoryCaptureCommandHandler.m_SwTraceMessages[index];
127
128 CHECK(bufferMessage.m_Name == handlerMessage.m_Name);
129 CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName);
130 CHECK(bufferMessage.m_Id == handlerMessage.m_Id);
131
132 CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size());
133 for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i)
134 {
135 CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]);
136 }
137
138 CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size());
139 for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i)
140 {
141 CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]);
142 }
143 }
144 }
145
146 TEST_CASE("TimelineCaptureTest")
147 {
148 arm::pipe::BufferManager bufferManager(50);
149 arm::pipe::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
150
151 std::unique_ptr<arm::pipe::ISendTimelinePacket> sendTimelinePacket =
152 timelinePacketWriterFactory.GetSendTimelinePacket();
153
154 arm::pipe::PacketVersionResolver packetVersionResolver;
155
156 arm::pipe::TimelineDecoder timelineDecoder;
157
158 arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
159 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder,
160 arm::pipe::ThreadIdSize);
161
162 using Status = arm::pipe::ITimelineDecoder::TimelineStatus;
163 CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success);
164 CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success);
165 CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success);
166 CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success);
167 CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success);
168
169 const uint64_t entityGuid = 111111u;
170 const uint64_t eventClassGuid = 22222u;
171 const uint64_t eventClassNameGuid = 22322u;
172 const uint64_t timestamp = 33333u;
173 const uint64_t eventGuid = 44444u;
174
175 const int threadId = arm::pipe::GetCurrentThreadId();
176
177 // need to do a bit of work here to extract the value from threadId
178 unsigned char* uCharThreadId = new unsigned char[arm::pipe::ThreadIdSize]();;
179 uint64_t uint64ThreadId;
180
181 arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, arm::pipe::ThreadIdSize);
182
183 if (arm::pipe::ThreadIdSize == 4)
184 {
185 uint64ThreadId = arm::pipe::ReadUint32(uCharThreadId, 0);
186 }
187 else if (arm::pipe::ThreadIdSize == 8)
188 {
189 uint64ThreadId = arm::pipe::ReadUint64(uCharThreadId, 0);
190 }
191 delete[] uCharThreadId;
192
193 const uint64_t labelGuid = 66666u;
194 std::string labelName = "test_label";
195
196 const uint64_t relationshipGuid = 77777u;
197 const uint64_t headGuid = 888888u;
198 const uint64_t tailGuid = 999999u;
199
200 for (int i = 0; i < 10; ++i)
201 {
202 // Send entity
203 sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
204 sendTimelinePacket->Commit();
205 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
206 timelineCaptureCommandHandler);
207
208 // Send event class
209 sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid, eventClassNameGuid);
210 sendTimelinePacket->Commit();
211 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
212 timelineCaptureCommandHandler);
213
214 // Send event
215 sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
216 sendTimelinePacket->Commit();
217 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
218 timelineCaptureCommandHandler);
219
220 // Send label
221 sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
222 sendTimelinePacket->Commit();
223 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
224 timelineCaptureCommandHandler);
225
226 // Send relationship
227 arm::pipe::ProfilingRelationshipType relationshipType =
228 arm::pipe::ProfilingRelationshipType::DataLink;
229 sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
230 relationshipGuid,
231 headGuid,
232 tailGuid,
233 0);
234 sendTimelinePacket->Commit();
235 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
236 timelineCaptureCommandHandler);
237 }
238
__anonf0e442810102(const arm::pipe::TimelineDecoder::Model& model)239 timelineDecoder.ApplyToModel([&](const arm::pipe::TimelineDecoder::Model& model){
240 for (unsigned long i = 0; i < 10; ++i)
241 {
242 CHECK(model.m_Entities[i].m_Guid == entityGuid);
243
244 CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid);
245
246 CHECK(model.m_Events[i].m_TimeStamp == timestamp);
247 CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId);
248 CHECK(model.m_Events[i].m_Guid == eventGuid);
249
250 CHECK(model.m_Labels[i].m_Guid == labelGuid);
251 CHECK(model.m_Labels[i].m_Name == labelName);
252
253 CHECK(model.m_Relationships[i].m_RelationshipType ==
254 arm::pipe::ITimelineDecoder::RelationshipType::DataLink);
255 CHECK(model.m_Relationships[i].m_Guid == relationshipGuid);
256 CHECK(model.m_Relationships[i].m_HeadGuid == headGuid);
257 CHECK(model.m_Relationships[i].m_TailGuid == tailGuid);
258 }
259 });
260 }
261
262 TEST_CASE("TimelineCaptureTestMultipleStringsInBuffer")
263 {
264 arm::pipe::BufferManager bufferManager(50);
265 arm::pipe::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
266
267 std::unique_ptr<arm::pipe::ISendTimelinePacket> sendTimelinePacket =
268 timelinePacketWriterFactory.GetSendTimelinePacket();
269
270 arm::pipe::PacketVersionResolver packetVersionResolver;
271
272 arm::pipe::TimelineDecoder timelineDecoder;
273
274 arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
275 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder,
276 arm::pipe::ThreadIdSize);
277
278 using Status = arm::pipe::TimelineDecoder::TimelineStatus;
279 CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success);
280 CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success);
281 CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success);
282 CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success);
283 CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success);
284
285 const uint64_t entityGuid = 111111u;
286 const uint64_t eventClassGuid = 22222u;
287 const uint64_t eventClassNameGuid = 22322u;
288 const uint64_t timestamp = 33333u;
289 const uint64_t eventGuid = 44444u;
290
291 const int threadId = arm::pipe::GetCurrentThreadId();
292
293 // need to do a bit of work here to extract the value from threadId
294 unsigned char* uCharThreadId = new unsigned char[arm::pipe::ThreadIdSize]();
295 uint64_t uint64ThreadId;
296
297 arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, arm::pipe::ThreadIdSize);
298
299 if ( arm::pipe::ThreadIdSize == 4 )
300 {
301 uint64ThreadId = arm::pipe::ReadUint32(uCharThreadId, 0);
302 }
303 else if ( arm::pipe::ThreadIdSize == 8 )
304 {
305 uint64ThreadId = arm::pipe::ReadUint64(uCharThreadId, 0);
306 }
307 delete[] uCharThreadId;
308
309 const uint64_t labelGuid = 66666u;
310 std::string labelName = "test_label";
311 std::string labelName2 = "test_label2";
312 std::string labelName3 = "test_label32";
313
314 const uint64_t relationshipGuid = 77777u;
315 const uint64_t headGuid = 888888u;
316 const uint64_t tailGuid = 999999u;
317
318 // Check with multiple messages in the same buffer
319 for ( int i = 0; i < 9; ++i )
320 {
321 // Send entity
322 sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
323 // Send event class
324 sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid, eventClassNameGuid);
325 // Send event
326 sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
327 // Send label
328 sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
329 sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName2);
330 sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName3);
331 // Send relationship
332 arm::pipe::ProfilingRelationshipType relationshipType =
333 arm::pipe::ProfilingRelationshipType::DataLink;
334 sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
335 relationshipGuid,
336 headGuid,
337 tailGuid,
338 0);
339 }
340
341 sendTimelinePacket->Commit();
342 SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
343 timelineCaptureCommandHandler);
344
__anonf0e442810202(const arm::pipe::TimelineDecoder::Model& model)345 timelineDecoder.ApplyToModel([&](const arm::pipe::TimelineDecoder::Model& model){
346 for ( unsigned long i = 0; i < 9; ++i )
347 {
348 CHECK(model.m_Entities[i].m_Guid == entityGuid);
349
350 CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid);
351
352 CHECK(model.m_Labels[i].m_Guid == labelGuid);
353
354 CHECK(model.m_Events[i].m_TimeStamp == timestamp);
355 CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId);
356 CHECK(model.m_Events[i].m_Guid == eventGuid);
357
358 CHECK(model.m_Relationships[i].m_RelationshipType ==
359 arm::pipe::ITimelineDecoder::RelationshipType::DataLink);
360 CHECK(model.m_Relationships[i].m_Guid == relationshipGuid);
361 CHECK(model.m_Relationships[i].m_HeadGuid == headGuid);
362 CHECK(model.m_Relationships[i].m_TailGuid == tailGuid);
363 }
364 for ( unsigned long i = 0; i < 9; i += 3 )
365 {
366 CHECK(model.m_Labels[i].m_Name == labelName);
367 CHECK(model.m_Labels[i+1].m_Name == labelName2);
368 CHECK(model.m_Labels[i+2].m_Name == labelName3);
369 }
370 });
371 }
372
373 }
374