// // Copyright © 2019 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include #include #include #include #include #include #include #include #include #include #include TEST_SUITE("TimelineDecoderTests") { void SendTimelinePacketToCommandHandler(const unsigned char* packetBuffer, arm::pipe::CommandHandlerFunctor& CommandHandler) { uint32_t uint32_t_size = sizeof(uint32_t); unsigned int offset = 0; uint32_t header[2]; header[0] = arm::pipe::ReadUint32(packetBuffer, offset); offset += uint32_t_size; header[1] = arm::pipe::ReadUint32(packetBuffer, offset); offset += uint32_t_size; uint32_t PacketDataLength = header[1] & 0x00FFFFFF; auto uniquePacketData = std::make_unique(PacketDataLength); std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength); arm::pipe::Packet packet(header[0], PacketDataLength, uniquePacketData); CHECK(std::memcmp(packetBuffer + offset, packet.GetData(), packet.GetLength()) == 0); CommandHandler(packet); } void PushEntity(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Entity entity) { model.m_Entities.emplace_back(entity); } void PushEventClass(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::EventClass eventClass) { model.m_EventClasses.emplace_back(eventClass); } void PushEvent(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Event event) { model.m_Events.emplace_back(event); } void PushLabel(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Label label) { model.m_Labels.emplace_back(label); } void PushRelationship(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Relationship relationship) { model.m_Relationships.emplace_back(relationship); } 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); armnn::profiling::BufferManager bufferManager(5); armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); arm::pipe::PacketVersionResolver packetVersionResolver; arm::pipe::TimelineDecoder timelineDecoder; arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler( 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder); arm::pipe::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler( 1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(), timelineCaptureCommandHandler, true); sendTimelinePacket->SendTimelineMessageDirectoryPackage(); sendTimelinePacket->Commit(); std::vector swTraceBufferMessages; unsigned int offset = uint32_t_size * 2; std::unique_ptr packetBuffer = bufferManager.GetReadableBuffer(); uint8_t readStreamVersion = ReadUint8(packetBuffer, offset); CHECK(readStreamVersion == 4); offset += uint8_t_size; uint8_t readPointerBytes = ReadUint8(packetBuffer, offset); CHECK(readPointerBytes == uint64_t_size); offset += uint8_t_size; uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset); CHECK(readThreadIdBytes == armnn::profiling::ThreadIdSize); offset += uint8_t_size; uint32_t declarationSize = arm::pipe::ReadUint32(packetBuffer->GetReadableData(), offset); offset += uint32_t_size; for(uint32_t i = 0; i < declarationSize; ++i) { swTraceBufferMessages.push_back(arm::pipe::ReadSwTraceMessage(packetBuffer->GetReadableData(), offset, packetBuffer->GetSize())); } SendTimelinePacketToCommandHandler(packetBuffer->GetReadableData(), timelineDirectoryCaptureCommandHandler); for(uint32_t index = 0; index < declarationSize; ++index) { arm::pipe::SwTraceMessage& bufferMessage = swTraceBufferMessages[index]; arm::pipe::SwTraceMessage& handlerMessage = timelineDirectoryCaptureCommandHandler.m_SwTraceMessages[index]; CHECK(bufferMessage.m_Name == handlerMessage.m_Name); CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName); CHECK(bufferMessage.m_Id == handlerMessage.m_Id); CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size()); for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i) { CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]); } CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size()); for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i) { CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]); } } } TEST_CASE("TimelineCaptureTest") { armnn::profiling::BufferManager bufferManager(50); armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); arm::pipe::PacketVersionResolver packetVersionResolver; arm::pipe::TimelineDecoder timelineDecoder; const arm::pipe::TimelineDecoder::Model& model = timelineDecoder.GetModel(); arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler( 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, armnn::profiling::ThreadIdSize); using Status = arm::pipe::ITimelineDecoder::TimelineStatus; CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success); const uint64_t entityGuid = 111111u; const uint64_t eventClassGuid = 22222u; const uint64_t eventClassNameGuid = 22322u; const uint64_t timestamp = 33333u; const uint64_t eventGuid = 44444u; const int threadId = armnnUtils::Threads::GetCurrentThreadId(); // need to do a bit of work here to extract the value from threadId unsigned char* uCharThreadId = new unsigned char[armnn::profiling::ThreadIdSize]();; uint64_t uint64ThreadId; arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, armnn::profiling::ThreadIdSize); if (armnn::profiling::ThreadIdSize == 4) { uint64ThreadId = arm::pipe::ReadUint32(uCharThreadId, 0); } else if (armnn::profiling::ThreadIdSize == 8) { uint64ThreadId = arm::pipe::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, eventClassNameGuid); 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 armnn::profiling::ProfilingRelationshipType relationshipType = armnn::profiling::ProfilingRelationshipType::DataLink; sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType, relationshipGuid, headGuid, tailGuid, 0); sendTimelinePacket->Commit(); SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), timelineCaptureCommandHandler); } for (unsigned long i = 0; i < 10; ++i) { CHECK(model.m_Entities[i].m_Guid == entityGuid); CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); CHECK(model.m_Events[i].m_TimeStamp == timestamp); CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); CHECK(model.m_Events[i].m_Guid == eventGuid); CHECK(model.m_Labels[i].m_Guid == labelGuid); CHECK(model.m_Labels[i].m_Name == labelName); CHECK(model.m_Relationships[i].m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::DataLink); CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); } } TEST_CASE("TimelineCaptureTestMultipleStringsInBuffer") { armnn::profiling::BufferManager bufferManager(50); armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); std::unique_ptr sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket(); arm::pipe::PacketVersionResolver packetVersionResolver; arm::pipe::TimelineDecoder timelineDecoder; const arm::pipe::TimelineDecoder::Model& model = timelineDecoder.GetModel(); arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler( 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, armnn::profiling::ThreadIdSize); using Status = arm::pipe::TimelineDecoder::TimelineStatus; CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success); CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success); const uint64_t entityGuid = 111111u; const uint64_t eventClassGuid = 22222u; const uint64_t eventClassNameGuid = 22322u; const uint64_t timestamp = 33333u; const uint64_t eventGuid = 44444u; const int threadId = armnnUtils::Threads::GetCurrentThreadId(); // need to do a bit of work here to extract the value from threadId unsigned char* uCharThreadId = new unsigned char[armnn::profiling::ThreadIdSize](); uint64_t uint64ThreadId; arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, armnn::profiling::ThreadIdSize); if ( armnn::profiling::ThreadIdSize == 4 ) { uint64ThreadId = arm::pipe::ReadUint32(uCharThreadId, 0); } else if ( armnn::profiling::ThreadIdSize == 8 ) { uint64ThreadId = arm::pipe::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, eventClassNameGuid); // Send event sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid); // Send label sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName); sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName2); sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName3); // Send relationship armnn::profiling::ProfilingRelationshipType relationshipType = armnn::profiling::ProfilingRelationshipType::DataLink; sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType, relationshipGuid, headGuid, tailGuid, 0); } sendTimelinePacket->Commit(); SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), timelineCaptureCommandHandler); for ( unsigned long i = 0; i < 9; ++i ) { CHECK(model.m_Entities[i].m_Guid == entityGuid); CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); CHECK(model.m_Labels[i].m_Guid == labelGuid); CHECK(model.m_Events[i].m_TimeStamp == timestamp); CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); CHECK(model.m_Events[i].m_Guid == eventGuid); CHECK(model.m_Relationships[i].m_RelationshipType == arm::pipe::ITimelineDecoder::RelationshipType::DataLink); CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); } for ( unsigned long i = 0; i < 9; i += 3 ) { CHECK(model.m_Labels[i].m_Name == labelName); CHECK(model.m_Labels[i+1].m_Name == labelName2); CHECK(model.m_Labels[i+2].m_Name == labelName3); } } }