| // |
| // Copyright © 2019 Arm Ltd. All rights reserved. |
| // SPDX-License-Identifier: MIT |
| // |
| |
| #include <TimelineCaptureCommandHandler.hpp> |
| #include <TimelineDirectoryCaptureCommandHandler.hpp> |
| #include <TimelineDecoder.hpp> |
| |
| #include <CommandHandlerFunctor.hpp> |
| #include <ProfilingService.hpp> |
| #include <PacketBuffer.hpp> |
| #include <TimelinePacketWriterFactory.hpp> |
| |
| #include <boost/test/test_tools.hpp> |
| #include <boost/test/unit_test_suite.hpp> |
| |
| BOOST_AUTO_TEST_SUITE(TimelineDecoderTests) |
| |
| using namespace armnn; |
| using namespace timelinedecoder; |
| |
| void SendTimelinePacketToCommandHandler(const unsigned char* packetBuffer, |
| profiling::CommandHandlerFunctor &CommandHandler) |
| { |
| uint32_t uint32_t_size = sizeof(uint32_t); |
| unsigned int offset = 0; |
| |
| uint32_t header[2]; |
| header[0] = profiling::ReadUint32(packetBuffer, offset); |
| offset += uint32_t_size; |
| header[1] = profiling::ReadUint32(packetBuffer, offset); |
| offset += uint32_t_size; |
| uint32_t PacketDataLength = header[1] & 0x00FFFFFF; |
| |
| auto uniquePacketData = std::make_unique<unsigned char[]>(PacketDataLength); |
| std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength); |
| |
| armnn::profiling::Packet packet(header[0], PacketDataLength, uniquePacketData); |
| |
| BOOST_CHECK(std::memcmp(packetBuffer + offset, packet.GetData(), packet.GetLength()) == 0); |
| |
| CommandHandler(packet); |
| } |
| |
| void PushEntity(TimelineDecoder::Model& model, const ITimelineDecoder::Entity entity) |
| { |
| model.m_Entities.emplace_back(entity); |
| } |
| |
| void PushEventClass(TimelineDecoder::Model& model, const ITimelineDecoder::EventClass eventClass) |
| { |
| model.m_EventClasses.emplace_back(eventClass); |
| } |
| |
| void PushEvent(TimelineDecoder::Model& model, const ITimelineDecoder::Event event) |
| { |
| model.m_Events.emplace_back(event); |
| } |
| |
| void PushLabel(TimelineDecoder::Model& model, const ITimelineDecoder::Label label) |
| { |
| model.m_Labels.emplace_back(label); |
| } |
| |
| void PushRelationship(TimelineDecoder::Model& model, const ITimelineDecoder::Relationship relationship) |
| { |
| model.m_Relationships.emplace_back(relationship); |
| } |
| |
| BOOST_AUTO_TEST_CASE(TimelineDirectoryTest) |
| { |
| uint32_t uint8_t_size = sizeof(uint8_t); |
| uint32_t uint32_t_size = sizeof(uint32_t); |
| uint32_t uint64_t_size = sizeof(uint64_t); |
| uint32_t threadId_size = sizeof(std::thread::id); |
| |
| profiling::BufferManager bufferManager(5); |
| profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); |
| |
| std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = |
| timelinePacketWriterFactory.GetSendTimelinePacket(); |
| |
| profiling::PacketVersionResolver packetVersionResolver; |
| |
| TimelineDecoder timelineDecoder; |
| TimelineCaptureCommandHandler timelineCaptureCommandHandler( |
| 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder); |
| |
| TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler( |
| 1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(), |
| timelineCaptureCommandHandler, true); |
| |
| sendTimelinePacket->SendTimelineMessageDirectoryPackage(); |
| sendTimelinePacket->Commit(); |
| |
| std::vector<profiling::SwTraceMessage> swTraceBufferMessages; |
| |
| unsigned int offset = uint32_t_size * 2; |
| |
| std::unique_ptr<profiling::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer(); |
| |
| uint8_t readStreamVersion = ReadUint8(packetBuffer, offset); |
| BOOST_CHECK(readStreamVersion == 4); |
| offset += uint8_t_size; |
| uint8_t readPointerBytes = ReadUint8(packetBuffer, offset); |
| BOOST_CHECK(readPointerBytes == uint64_t_size); |
| offset += uint8_t_size; |
| uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset); |
| BOOST_CHECK(readThreadIdBytes == threadId_size); |
| offset += uint8_t_size; |
| |
| uint32_t declarationSize = profiling::ReadUint32(packetBuffer, offset); |
| offset += uint32_t_size; |
| for(uint32_t i = 0; i < declarationSize; ++i) |
| { |
| swTraceBufferMessages.push_back(profiling::ReadSwTraceMessage(packetBuffer->GetReadableData(), offset)); |
| } |
| |
| SendTimelinePacketToCommandHandler(packetBuffer->GetReadableData(), timelineDirectoryCaptureCommandHandler); |
| |
| for(uint32_t index = 0; index < declarationSize; ++index) |
| { |
| profiling::SwTraceMessage& bufferMessage = swTraceBufferMessages[index]; |
| profiling::SwTraceMessage& handlerMessage = timelineDirectoryCaptureCommandHandler.m_SwTraceMessages[index]; |
| |
| BOOST_CHECK(bufferMessage.m_Name == handlerMessage.m_Name); |
| BOOST_CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName); |
| BOOST_CHECK(bufferMessage.m_Id == handlerMessage.m_Id); |
| |
| BOOST_CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size()); |
| for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i) |
| { |
| BOOST_CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]); |
| } |
| |
| BOOST_CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size()); |
| for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i) |
| { |
| BOOST_CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]); |
| } |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(TimelineCaptureTest) |
| { |
| unsigned int threadIdSize = sizeof(std::thread::id); |
| profiling::BufferManager bufferManager(50); |
| profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); |
| |
| std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = |
| timelinePacketWriterFactory.GetSendTimelinePacket(); |
| |
| profiling::PacketVersionResolver packetVersionResolver; |
| |
| TimelineDecoder timelineDecoder; |
| const TimelineDecoder::Model& model = timelineDecoder.GetModel(); |
| |
| |
| TimelineCaptureCommandHandler timelineCaptureCommandHandler( |
| 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, threadIdSize); |
| |
| using Status = ITimelineDecoder::TimelineStatus; |
| BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success); |
| |
| const uint64_t entityGuid = 111111u; |
| const uint64_t eventClassGuid = 22222u; |
| const uint64_t timestamp = 33333u; |
| const uint64_t eventGuid = 44444u; |
| |
| const std::thread::id threadId = std::this_thread::get_id(); |
| |
| // need to do a bit of work here to extract the value from threadId |
| unsigned char* uCharThreadId = new unsigned char[threadIdSize]();; |
| uint64_t uint64ThreadId; |
| |
| profiling::WriteBytes(uCharThreadId, 0, &threadId, threadIdSize); |
| |
| if (threadIdSize == 4) |
| { |
| uint64ThreadId = profiling::ReadUint32(uCharThreadId, 0); |
| } |
| else if (threadIdSize == 8) |
| { |
| uint64ThreadId = profiling::ReadUint64(uCharThreadId, 0); |
| } |
| delete[] uCharThreadId; |
| |
| const uint64_t labelGuid = 66666u; |
| std::string labelName = "test_label"; |
| |
| const uint64_t relationshipGuid = 77777u; |
| const uint64_t headGuid = 888888u; |
| const uint64_t tailGuid = 999999u; |
| |
| for (int i = 0; i < 10; ++i) |
| { |
| // Send entity |
| sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid); |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| |
| // Send event class |
| sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid); |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| |
| // Send event |
| sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid); |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| |
| // Send label |
| sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName); |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| |
| // Send relationship |
| profiling::ProfilingRelationshipType relationshipType = profiling::ProfilingRelationshipType::DataLink; |
| sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType, |
| relationshipGuid, |
| headGuid, |
| tailGuid); |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| } |
| |
| for (unsigned long i = 0; i < 10; ++i) |
| { |
| BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid); |
| |
| BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); |
| |
| BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp); |
| BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); |
| BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid); |
| |
| BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid); |
| BOOST_CHECK(model.m_Labels[i].m_Name == labelName); |
| |
| BOOST_CHECK(model.m_Relationships[i].m_RelationshipType == ITimelineDecoder::RelationshipType::DataLink); |
| BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); |
| BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); |
| BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); |
| } |
| } |
| |
| BOOST_AUTO_TEST_CASE(TimelineCaptureTestMultipleStringsInBuffer) |
| { |
| unsigned int threadIdSize = sizeof(std::thread::id); |
| profiling::BufferManager bufferManager(50); |
| profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); |
| |
| std::unique_ptr<profiling::ISendTimelinePacket> sendTimelinePacket = |
| timelinePacketWriterFactory.GetSendTimelinePacket(); |
| |
| profiling::PacketVersionResolver packetVersionResolver; |
| |
| TimelineDecoder timelineDecoder; |
| const TimelineDecoder::Model& model = timelineDecoder.GetModel(); |
| |
| TimelineCaptureCommandHandler timelineCaptureCommandHandler( |
| 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, threadIdSize); |
| |
| using Status = ITimelineDecoder::TimelineStatus; |
| BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success); |
| BOOST_CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success); |
| |
| const uint64_t entityGuid = 111111u; |
| const uint64_t eventClassGuid = 22222u; |
| const uint64_t timestamp = 33333u; |
| const uint64_t eventGuid = 44444u; |
| |
| const std::thread::id threadId = std::this_thread::get_id(); |
| |
| // need to do a bit of work here to extract the value from threadId |
| unsigned char* uCharThreadId = new unsigned char[threadIdSize]();; |
| uint64_t uint64ThreadId; |
| |
| profiling::WriteBytes(uCharThreadId, 0, &threadId, threadIdSize); |
| |
| if ( threadIdSize == 4 ) |
| { |
| uint64ThreadId = profiling::ReadUint32(uCharThreadId, 0); |
| } else if ( threadIdSize == 8 ) |
| { |
| uint64ThreadId = profiling::ReadUint64(uCharThreadId, 0); |
| } |
| delete[] uCharThreadId; |
| |
| const uint64_t labelGuid = 66666u; |
| std::string labelName = "test_label"; |
| std::string labelName2 = "test_label2"; |
| std::string labelName3 = "test_label32"; |
| |
| const uint64_t relationshipGuid = 77777u; |
| const uint64_t headGuid = 888888u; |
| const uint64_t tailGuid = 999999u; |
| |
| // Check with multiple messages in the same buffer |
| for ( int i = 0; i < 9; ++i ) |
| { |
| // Send entity |
| sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid); |
| // Send event class |
| sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid); |
| // Send event |
| sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid); |
| // Send label |
| sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName); |
| sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName2); |
| sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName3); |
| // Send relationship |
| profiling::ProfilingRelationshipType relationshipType = profiling::ProfilingRelationshipType::DataLink; |
| sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType, |
| relationshipGuid, |
| headGuid, |
| tailGuid); |
| } |
| |
| sendTimelinePacket->Commit(); |
| SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), |
| timelineCaptureCommandHandler); |
| |
| for ( unsigned long i = 0; i < 9; ++i ) |
| { |
| BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid); |
| |
| BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); |
| |
| BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid); |
| |
| BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp); |
| BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); |
| BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid); |
| |
| BOOST_CHECK(model.m_Relationships[i].m_RelationshipType == ITimelineDecoder::RelationshipType::DataLink); |
| BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); |
| BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); |
| BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); |
| } |
| for ( unsigned long i = 0; i < 9; i += 3 ) |
| { |
| BOOST_CHECK(model.m_Labels[i].m_Name == labelName); |
| BOOST_CHECK(model.m_Labels[i+1].m_Name == labelName2); |
| BOOST_CHECK(model.m_Labels[i+2].m_Name == labelName3); |
| } |
| } |
| |
| BOOST_AUTO_TEST_SUITE_END() |