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