From e63a026bd987e78bdaa5b94c3e53201b62011faa Mon Sep 17 00:00:00 2001 From: Finn Williams Date: Tue, 22 Oct 2019 10:30:49 +0100 Subject: IVGCVSW-3951 Create the timeline decoder * Added ITimelineDecoder.h C interface * Added an example implementation of ITimelineDecoder.h * Added command handlers for the timeline directory and objects * Added tests for the decoder implementation * Changed ReadSwTraceMessage to take a const unsigned char* so it can be used by the directory command handler * Fixed some bugs in ProfilingUtils.cpp and related tests Change-Id: If06faf1fe0274a8f022f194a6d3527f5ce5374c6 Signed-off-by: Finn Williams --- CMakeLists.txt | 8 + src/profiling/DirectoryCaptureCommandHandler.cpp | 1 + src/profiling/ProfilingUtils.cpp | 16 +- src/profiling/ProfilingUtils.hpp | 2 +- src/profiling/test/SendTimelinePacketTests.cpp | 18 +- src/profiling/test/TimelinePacketTests.cpp | 7 +- src/profiling/test/TimelineUtilityMethodsTests.cpp | 2 +- tests/profiling/timelineDecoder/ITimelineDecoder.h | 41 +++ .../TimelineCaptureCommandHandler.cpp | 300 +++++++++++++++++++++ .../TimelineCaptureCommandHandler.hpp | 66 +++++ .../profiling/timelineDecoder/TimelineDecoder.cpp | 166 ++++++++++++ .../TimelineDirectoryCaptureCommandHandler.cpp | 106 ++++++++ .../TimelineDirectoryCaptureCommandHandler.hpp | 47 ++++ tests/profiling/timelineDecoder/TimelineModel.h | 96 +++++++ .../tests/TimelineTestFunctions.hpp | 143 ++++++++++ .../timelineDecoder/tests/TimelineTests.cpp | 206 ++++++++++++++ 16 files changed, 1208 insertions(+), 17 deletions(-) create mode 100644 tests/profiling/timelineDecoder/ITimelineDecoder.h create mode 100644 tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp create mode 100644 tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp create mode 100644 tests/profiling/timelineDecoder/TimelineDecoder.cpp create mode 100644 tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp create mode 100644 tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp create mode 100644 tests/profiling/timelineDecoder/TimelineModel.h create mode 100644 tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp create mode 100644 tests/profiling/timelineDecoder/tests/TimelineTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 867fb34071..5b80430d7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -822,6 +822,7 @@ if(BUILD_UNIT_TESTS) if(BUILD_GATORD_MOCK) list(APPEND unittest_sources tests/profiling/gatordmock/tests/GatordMockTests.cpp + tests/profiling/timelineDecoder/tests/TimelineTests.cpp ) endif() @@ -936,6 +937,13 @@ if(BUILD_GATORD_MOCK) tests/profiling/gatordmock/PeriodicCounterCaptureCommandHandler.hpp tests/profiling/gatordmock/PeriodicCounterSelectionResponseHandler.cpp tests/profiling/gatordmock/PeriodicCounterSelectionResponseHandler.hpp + tests/profiling/timelineDecoder/ITimelineDecoder.h + tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp + tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp + tests/profiling/timelineDecoder/TimelineDecoder.cpp + tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp + tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp + tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp ) include_directories(${Boost_INCLUDE_DIRS} src/profiling) diff --git a/src/profiling/DirectoryCaptureCommandHandler.cpp b/src/profiling/DirectoryCaptureCommandHandler.cpp index 22d1e6d0dd..c5a2d97293 100644 --- a/src/profiling/DirectoryCaptureCommandHandler.cpp +++ b/src/profiling/DirectoryCaptureCommandHandler.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: MIT // +#include #include "DirectoryCaptureCommandHandler.hpp" #include "SendCounterPacket.hpp" diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp index b649747df1..4dde235ecc 100644 --- a/src/profiling/ProfilingUtils.cpp +++ b/src/profiling/ProfilingUtils.cpp @@ -347,7 +347,7 @@ uint32_t CalculateSizeOfPaddedSwString(const std::string& str) } // Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset -SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned int& offset) +SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned int& offset) { BOOST_ASSERT(packetBuffer); @@ -369,7 +369,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned offset += uint32_t_size; std::vector swTraceStringBuffer(swTraceDeclNameLength - 1); std::memcpy(swTraceStringBuffer.data(), - packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + packetBuffer + offset, swTraceStringBuffer.size()); swTraceMessage.name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name @@ -380,7 +380,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned offset += uint32_t_size; swTraceStringBuffer.resize(swTraceUINameLength - 1); std::memcpy(swTraceStringBuffer.data(), - packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + packetBuffer + offset, swTraceStringBuffer.size()); swTraceMessage.uiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name @@ -391,7 +391,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned offset += uint32_t_size; swTraceStringBuffer.resize(swTraceArgTypesLength - 1); std::memcpy(swTraceStringBuffer.data(), - packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + packetBuffer + offset, swTraceStringBuffer.size()); swTraceMessage.argTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types @@ -404,7 +404,7 @@ SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned offset += uint32_t_size; swTraceStringBuffer.resize(swTraceArgNamesLength - 1); std::memcpy(swTraceStringBuffer.data(), - packetBuffer->GetReadableData() + offset, swTraceStringBuffer.size()); + packetBuffer + offset, swTraceStringBuffer.size()); swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); std::stringstream stringStream(swTraceString); @@ -536,12 +536,11 @@ TimelinePacketStatus WriteTimelineEntityBinaryPacket(uint64_t profilingGuid, unsigned int uint64_t_size = sizeof(uint64_t); // Calculate the length of the data (in bytes) - unsigned int timelineEntityPacketDataLength = uint64_t_size; // Profiling GUID + unsigned int timelineEntityPacketDataLength = uint32_t_size + uint64_t_size; // decl_id + Profiling GUID // Calculate the timeline binary packet size (in bytes) unsigned int timelineEntityPacketSize = 2 * uint32_t_size + // Header (2 words) - uint32_t_size + // decl_Id timelineEntityPacketDataLength; // Profiling GUID // Check whether the timeline binary packet fits in the given buffer @@ -744,6 +743,9 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer, WriteUint32(buffer, offset, packetHeader.second); offset += uint32_t_size; + WriteUint32(buffer, offset, static_cast(swTraceTimelineDirectoryMessages.size())); + offset += uint32_t_size; + for (unsigned int i = 0u; i < swTraceTimelineDirectoryMessages.size(); ++i) { // Write the timeline binary packet payload to the buffer diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp index 74fc437333..f7b46be972 100644 --- a/src/profiling/ProfilingUtils.hpp +++ b/src/profiling/ProfilingUtils.hpp @@ -156,7 +156,7 @@ enum class ProfilingRelationshipType uint32_t CalculateSizeOfPaddedSwString(const std::string& str); -SwTraceMessage ReadSwTraceMessage(const IPacketBufferPtr& packetBuffer, unsigned int& offset); +SwTraceMessage ReadSwTraceMessage(const unsigned char*, unsigned int& offset); TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label, diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp index 60cda9a657..7f3094918d 100644 --- a/src/profiling/test/SendTimelinePacketTests.cpp +++ b/src/profiling/test/SendTimelinePacketTests.cpp @@ -53,7 +53,11 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) BOOST_CHECK(dataLength == 416); offset += uint32_t_size; - SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + uint32_t DeclCount = ReadUint32(packetBuffer, offset); + BOOST_CHECK(DeclCount == 5); + + offset += uint32_t_size; + SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset); BOOST_CHECK(swTraceMessage.id == 0); BOOST_CHECK(swTraceMessage.name == "declareLabel"); @@ -65,7 +69,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); BOOST_CHECK(swTraceMessage.argNames[1] == "value"); - swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset); BOOST_CHECK(swTraceMessage.id == 1); BOOST_CHECK(swTraceMessage.name == "declareEntity"); @@ -75,7 +79,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) BOOST_CHECK(swTraceMessage.argNames.size() == 1); BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); - swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset); BOOST_CHECK(swTraceMessage.id == 2); BOOST_CHECK(swTraceMessage.name == "declareEventClass"); @@ -85,7 +89,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) BOOST_CHECK(swTraceMessage.argNames.size() == 1); BOOST_CHECK(swTraceMessage.argNames[0] == "guid"); - swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset); BOOST_CHECK(swTraceMessage.id == 3); BOOST_CHECK(swTraceMessage.name == "declareRelationship"); @@ -101,7 +105,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest) BOOST_CHECK(swTraceMessage.argNames[2] == "headGuid"); BOOST_CHECK(swTraceMessage.argNames[3] == "tailGuid"); - swTraceMessage = ReadSwTraceMessage(packetBuffer, offset); + swTraceMessage = ReadSwTraceMessage(packetBuffer->GetReadableData(), offset); BOOST_CHECK(swTraceMessage.id == 4); BOOST_CHECK(swTraceMessage.name == "declareEvent"); @@ -157,7 +161,7 @@ BOOST_AUTO_TEST_CASE(SendTimelineEntityPlusEventClassBinaryPacketTest) uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0); - BOOST_CHECK(entityBinaryPacketDataLength == 8); + BOOST_CHECK(entityBinaryPacketDataLength == 12); // Check the decl_id offset += uint32_t_size; @@ -243,7 +247,7 @@ BOOST_AUTO_TEST_CASE(SendTimelinePacketTests1) uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0); - BOOST_CHECK(entityBinaryPacketDataLength == 8); + BOOST_CHECK(entityBinaryPacketDataLength == 12); // Check the decl_id offset += uint32_t_size; diff --git a/src/profiling/test/TimelinePacketTests.cpp b/src/profiling/test/TimelinePacketTests.cpp index 6a8aa85fc0..68cd948bdd 100644 --- a/src/profiling/test/TimelinePacketTests.cpp +++ b/src/profiling/test/TimelinePacketTests.cpp @@ -543,6 +543,11 @@ BOOST_AUTO_TEST_CASE(TimelineMessageDirectoryPacketTest3) BOOST_CHECK(sequenceNumbered == 0); BOOST_CHECK(dataLength == 416); + // Check the number of declarations + offset += uint32_t_size; + uint32_t declCount = ReadUint32(buffer.data(), offset); + BOOST_CHECK(declCount == 5); + // Check the decl_id offset += uint32_t_size; uint32_t readDeclId = ReadUint32(buffer.data(), offset); @@ -689,7 +694,7 @@ BOOST_AUTO_TEST_CASE(TimelineEntityPacketTest4) uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001; uint32_t dataLength = (packetHeaderWord1 >> 0) & 0x00FFFFFF; BOOST_CHECK(sequenceNumbered == 0); - BOOST_CHECK(dataLength == 8); + BOOST_CHECK(dataLength == 12); // Check decl_Id offset += uint32_t_size; diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp index 3556a12a7b..f784afc6ef 100644 --- a/src/profiling/test/TimelineUtilityMethodsTests.cpp +++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp @@ -258,7 +258,7 @@ void VerifyTimelineEntityBinaryPacket(Optional guid, uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001; uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF; BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0); - BOOST_CHECK(entityBinaryPacketDataLength == 8); + BOOST_CHECK(entityBinaryPacketDataLength == 12); // Check the decl_id offset += uint32_t_size; diff --git a/tests/profiling/timelineDecoder/ITimelineDecoder.h b/tests/profiling/timelineDecoder/ITimelineDecoder.h new file mode 100644 index 0000000000..65ec8bfa6e --- /dev/null +++ b/tests/profiling/timelineDecoder/ITimelineDecoder.h @@ -0,0 +1,41 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#ifndef ARMNN_ITIMELINEDECODER_H +#define ARMNN_ITIMELINEDECODER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "TimelineModel.h" + +typedef enum ErrorCode +{ + ErrorCode_Success, + ErrorCode_Fail +} ErrorCode; + +ErrorCode CreateModel(Model** model); +ErrorCode DestroyModel(Model** model); + +ErrorCode SetEntityCallback(OnNewEntityCallback cb, Model* model); +ErrorCode SetEventClassCallback(OnNewEventClassCallback cb, Model* model); +ErrorCode SetEventCallback(OnNewEventCallback cb, Model* model); +ErrorCode SetLabelCallback(OnNewLabelCallback cb, Model* model); +ErrorCode SetRelationshipCallback(OnNewRelationshipCallback cb, Model* model); + +ErrorCode CreateEntity(const Entity entity, Model* model); +ErrorCode CreateEventClass(const EventClass eventClass, Model* model); +ErrorCode CreateEvent(const Event event, Model* model); +ErrorCode CreateLabel(const Label label, Model* model); +ErrorCode CreateRelationship(const Relationship relationship, Model* model); + +#ifdef __cplusplus +} +#endif + +#endif //ARMNN_ITIMELINEDECODER_H \ No newline at end of file diff --git a/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp new file mode 100644 index 0000000000..bdceca69b0 --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.cpp @@ -0,0 +1,300 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineCaptureCommandHandler.hpp" + +#include +#include + +namespace armnn +{ + +namespace gatordmock +{ + +//Array of member functions, the array index matches the decl_id +const TimelineCaptureCommandHandler::ReadFunction TimelineCaptureCommandHandler::m_ReadFunctions[5] +{ + &TimelineCaptureCommandHandler::ReadLabel, // Label decl_id = 0 + &TimelineCaptureCommandHandler::ReadEntity, // Entity decl_id = 1 + &TimelineCaptureCommandHandler::ReadEventClass, // EventClass decl_id = 2 + &TimelineCaptureCommandHandler::ReadRelationship, // Relationship decl_id = 3 + &TimelineCaptureCommandHandler::ReadEvent // Event decl_id = 4 +}; + +void TimelineCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet) +{ + uint32_t offset = 0; + + if (packet.GetLength() < 8) + { + return; + } + + const unsigned char* data = reinterpret_cast(packet.GetData()); + + uint32_t declId = 0; + + declId = profiling::ReadUint32(data, offset); + offset += uint32_t_size; + + (this->*m_ReadFunctions[declId])(data, offset); +} + +void TimelineCaptureCommandHandler::ReadLabel(const unsigned char* data, uint32_t offset) +{ + Label label; + label.m_Guid = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + uint32_t nameLength = profiling::ReadUint32(data, offset); + offset += uint32_t_size; + + label.m_Name = new char[nameLength]; + for (uint32_t i = 0; i< nameLength; ++i) + { + label.m_Name[i] = static_cast(profiling::ReadUint8(data, offset + i)); + } + + CreateLabel(label, m_Model); + + if (!m_QuietOperation) + { + printLabels(); + } +} + +void TimelineCaptureCommandHandler::ReadEntity(const unsigned char* data, uint32_t offset) +{ + Entity entity; + entity.m_Guid = profiling::ReadUint64(data, offset); + + CreateEntity(entity, m_Model); + + if (!m_QuietOperation) + { + printEntities(); + } +} + +void TimelineCaptureCommandHandler::ReadEventClass(const unsigned char* data, uint32_t offset) +{ + EventClass eventClass; + eventClass.m_Guid = profiling::ReadUint64(data, offset); + + CreateEventClass(eventClass, m_Model); + + if (!m_QuietOperation) + { + printEventClasses(); + } +} + +void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, uint32_t offset) +{ + Relationship relationship; + relationship.m_RelationshipType = static_cast(profiling::ReadUint32(data, offset)); + offset += uint32_t_size; + + relationship.m_Guid = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + relationship.m_HeadGuid = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + relationship.m_TailGuid = profiling::ReadUint64(data, offset); + + CreateRelationship(relationship, m_Model); + + if (!m_QuietOperation) + { + printRelationships(); + } +} + + + +void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_t offset) +{ + Event event; + event.m_TimeStamp = profiling::ReadUint64(data, offset); + offset += uint64_t_size; + + event.m_ThreadId = new u_int8_t[threadId_size]; + profiling::ReadBytes(data, offset, threadId_size, event.m_ThreadId); + offset += threadId_size; + + event.m_Guid = profiling::ReadUint64(data, offset); + + CreateEvent(event, m_Model); + + if (!m_QuietOperation) + { + printEvents(); + } +} + +void TimelineCaptureCommandHandler::operator()(const profiling::Packet& packet) +{ + ParseData(packet); +} + +void TimelineCaptureCommandHandler::printLabels() +{ + std::string header; + + header.append(profiling::CentreAlignFormatting("guid", 12)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("value", 30)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("LABELS", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + std::cout << header; + + for (uint32_t i = 0; i < m_Model->m_LabelCount; ++i) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Labels[i]->m_Guid), 12)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(m_Model->m_Labels[i]->m_Name, 30)); + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + std::cout<< body; + } +} + +void TimelineCaptureCommandHandler::printEntities() +{ + std::string header; + header.append(profiling::CentreAlignFormatting("guid", 12)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("ENTITIES", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + std::cout << header; + + for (uint32_t i = 0; i < m_Model->m_EntityCount; ++i) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Entities[i]->m_Guid), 12)); + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + std::cout<< body; + } +} + +void TimelineCaptureCommandHandler::printEventClasses() +{ + std::string header; + header.append(profiling::CentreAlignFormatting("guid", 12)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("EVENT CLASSES", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + std::cout << header; + + for (uint32_t i = 0; i < m_Model->m_EventClassCount; ++i) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_EventClasses[i]->m_Guid), 12)); + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + std::cout<< body; + } +} + +void TimelineCaptureCommandHandler::printRelationships() +{ + std::string header; + header.append(profiling::CentreAlignFormatting("relationshipType", 20)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("relationshipGuid", 20)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("headGuid", 12)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("tailGuid", 12)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("RELATIONSHIPS", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + std::cout << header; + + for (uint32_t i = 0; i < m_Model->m_RelationshipCount; ++i) + { + std::string body; + + body.append( + profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_RelationshipType), 20)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_Guid), 20)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_HeadGuid), 12)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Relationships[i]->m_TailGuid), 12)); + body.append(" | "); + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + std::cout<< body; + } +} + +void TimelineCaptureCommandHandler::printEvents() +{ + std::string header; + + header.append(profiling::CentreAlignFormatting("timestamp", 12)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("threadId", 12)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("eventGuid", 12)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("EVENTS", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + std::cout << header; + + for (uint32_t i = 0; i < m_Model->m_EventCount; ++i) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Events[i]->m_TimeStamp), 12)); + body.append(" | "); + + std::string threadId; + for(uint32_t j =0; j< threadId_size; j++) + { + threadId += static_cast(m_Model->m_Events[i]->m_ThreadId[j]); + } + body.append(profiling::CentreAlignFormatting(threadId, 12)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(std::to_string(m_Model->m_Events[i]->m_Guid), 12)); + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + std::cout<< body; + } +} + +} //namespace gatordmock + +} //namespace armnn diff --git a/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp new file mode 100644 index 0000000000..3f3240491f --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineCaptureCommandHandler.hpp @@ -0,0 +1,66 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "ITimelineDecoder.h" + +#include +#include +#include + +namespace armnn +{ + +namespace gatordmock +{ + +class TimelineCaptureCommandHandler : public profiling::CommandHandlerFunctor +{ + // Utils + uint32_t uint32_t_size = sizeof(uint32_t); + uint32_t uint64_t_size = sizeof(uint64_t); + uint32_t threadId_size = sizeof(std::thread::id); + + using ReadFunction = void (TimelineCaptureCommandHandler::*)(const unsigned char*, uint32_t); + +public: + TimelineCaptureCommandHandler(uint32_t familyId, + uint32_t packetId, + uint32_t version, + Model* model, + bool quietOperation = false) + : CommandHandlerFunctor(familyId, packetId, version) + , m_Model(model) + , m_QuietOperation(quietOperation) + {} + + void operator()(const armnn::profiling::Packet& packet) override; + + void ReadLabel(const unsigned char* data, uint32_t offset); + void ReadEntity(const unsigned char* data, uint32_t offset); + void ReadEventClass(const unsigned char* data, uint32_t offset); + void ReadRelationship(const unsigned char* data, uint32_t offset); + void ReadEvent(const unsigned char* data, uint32_t offset); + + void print(); + +private: + void ParseData(const armnn::profiling::Packet& packet); + + Model* m_Model; + bool m_QuietOperation; + static const ReadFunction m_ReadFunctions[]; + + void printLabels(); + void printEntities(); + void printEventClasses(); + void printRelationships(); + void printEvents(); +}; + +} //namespace gatordmock + +} //namespace armnn diff --git a/tests/profiling/timelineDecoder/TimelineDecoder.cpp b/tests/profiling/timelineDecoder/TimelineDecoder.cpp new file mode 100644 index 0000000000..b6f051b745 --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineDecoder.cpp @@ -0,0 +1,166 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ITimelineDecoder.h" + +ErrorCode CreateEntity(const Entity entity, Model* model) +{ + if (model == nullptr || model->m_EntityCb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EntityCb(entity, model); + return ErrorCode::ErrorCode_Success; +} + +ErrorCode CreateEventClass(const EventClass eventClass, Model* model) +{ + if (model == nullptr || model->m_EventClassCb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EventClassCb(eventClass, model); + return ErrorCode::ErrorCode_Success; +} + +ErrorCode CreateEvent(const Event event, Model* model) +{ + if (model == nullptr || model->m_EventCb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EventCb(event, model); + return ErrorCode::ErrorCode_Success; +} + +ErrorCode CreateLabel(const Label label, Model* model) +{ + if (model == nullptr || model->m_LabelCb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_LabelCb(label, model); + return ErrorCode::ErrorCode_Success; +} + +ErrorCode CreateRelationship(Relationship relationship, Model* model) +{ + if (model == nullptr || model->m_RelationshipCb == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_RelationshipCb(relationship, model); + return ErrorCode::ErrorCode_Success; +} + +ErrorCode SetEntityCallback(OnNewEntityCallback cb, Model* model) +{ + if (cb == nullptr || model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EntityCb = cb; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode SetEventClassCallback(OnNewEventClassCallback cb, Model* model) +{ + if (cb == nullptr || model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EventClassCb = cb; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode SetEventCallback(OnNewEventCallback cb, Model* model) +{ + if (cb == nullptr || model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_EventCb = cb; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode SetLabelCallback(OnNewLabelCallback cb, Model* model) +{ + if (cb == nullptr || model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_LabelCb = cb; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode SetRelationshipCallback(OnNewRelationshipCallback cb, Model* model) +{ + if (cb == nullptr || model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + model->m_RelationshipCb = cb; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode CreateModel(Model** model) +{ + Model* modelPtr = new Model; + + modelPtr->m_EntityCount = 0; + modelPtr->m_EventClassCount = 0; + modelPtr->m_EventCount = 0; + modelPtr->m_LabelCount = 0; + modelPtr->m_RelationshipCount = 0; + + *model = modelPtr; + return ErrorCode::ErrorCode_Success; +} + +ErrorCode DestroyModel(Model** model) +{ + if (*model == nullptr) + { + return ErrorCode::ErrorCode_Fail; + } + + Model* modelPtr = *model; + + for (uint32_t i = 0; i < modelPtr->m_EntityCount; ++i) + { + delete modelPtr->m_Entities[i]; + } + + for (uint32_t i = 0; i < modelPtr->m_EventClassCount; ++i) + { + delete modelPtr->m_EventClasses[i]; + } + + for (uint32_t i = 0; i < modelPtr->m_EventCount; ++i) + { + delete[] modelPtr->m_Events[i]->m_ThreadId; + delete modelPtr->m_Events[i]; + } + + for (uint32_t i = 0; i < modelPtr->m_LabelCount; ++i) + { + delete[] modelPtr->m_Labels[i]->m_Name; + delete modelPtr->m_Labels[i]; + } + + for (uint32_t i = 0; i < modelPtr->m_RelationshipCount; ++i) + { + delete modelPtr->m_Relationships[i]; + } + + delete[] modelPtr->m_Entities; + delete[] modelPtr->m_EventClasses; + delete[] modelPtr->m_Events; + delete[] modelPtr->m_Labels; + delete[] modelPtr->m_Relationships; + + delete modelPtr; + return ErrorCode::ErrorCode_Success; +} \ No newline at end of file diff --git a/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp new file mode 100644 index 0000000000..cb860a950b --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.cpp @@ -0,0 +1,106 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TimelineDirectoryCaptureCommandHandler.hpp" + +#include +#include + +namespace armnn +{ + +namespace gatordmock +{ + +void TimelineDirectoryCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet) +{ + uint32_t offset = 0; + + if (packet.GetLength() < 8) + { + return; + } + + const unsigned char* data = packet.GetData(); + + uint32_t numberOfDeclarations = profiling::ReadUint32(data, offset); + offset += uint32_t_size; + + for (uint32_t declaration = 0; declaration < numberOfDeclarations; ++declaration) + { + m_SwTraceMessages.push_back(profiling::ReadSwTraceMessage(data, offset)); + } +} + +void TimelineDirectoryCaptureCommandHandler::Print() +{ + std::string header; + + header.append(profiling::CentreAlignFormatting("decl_id", 12)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("decl_name", 20)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("ui_name", 20)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("arg_types", 16)); + header.append(" | "); + header.append(profiling::CentreAlignFormatting("arg_names", 80)); + header.append("\n"); + + std::cout << "\n" << "\n"; + std::cout << profiling::CentreAlignFormatting("SW DIRECTORY", static_cast(header.size())); + std::cout << "\n"; + std::cout << std::string(header.size(), '=') << "\n"; + + std::cout<< header; + + for (auto swTraceMessage : m_SwTraceMessages) + { + std::string body; + + body.append(profiling::CentreAlignFormatting(std::to_string(swTraceMessage.id), 12)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(swTraceMessage.name, 20)); + body.append(" | "); + body.append(profiling::CentreAlignFormatting(swTraceMessage.uiName, 20)); + body.append(" | "); + + std::string argTypes; + for(auto argType: swTraceMessage.argTypes) + { + argTypes += argType; + argTypes += " "; + } + body.append(profiling::CentreAlignFormatting(argTypes, 16)); + body.append(" | "); + + std::string argNames; + for(auto argName: swTraceMessage.argNames) + { + argNames += argName + " "; + } + body.append(profiling::CentreAlignFormatting(argNames, 80)); + + body.append("\n"); + + std::cout << std::string(body.size(), '-') << "\n"; + + std::cout<< body; + } +} + +void TimelineDirectoryCaptureCommandHandler::operator()(const profiling::Packet& packet) +{ + ParseData(packet); + + if(!m_QuietOperation) + { + Print(); + } +} + +} //namespace gatordmock + +} //namespace armnn \ No newline at end of file diff --git a/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp new file mode 100644 index 0000000000..3a575d7fef --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp @@ -0,0 +1,47 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + + +#include +#include +#include +#include + +namespace armnn +{ + +namespace gatordmock +{ + +class TimelineDirectoryCaptureCommandHandler : public profiling::CommandHandlerFunctor +{ + // Utils + uint32_t uint32_t_size = sizeof(uint32_t); + +public: + TimelineDirectoryCaptureCommandHandler(uint32_t familyId, + uint32_t packetId, + uint32_t version, + bool quietOperation = false) + : CommandHandlerFunctor(familyId, packetId, version) + , m_QuietOperation(quietOperation) + {} + + void operator()(const armnn::profiling::Packet& packet) override; + + std::vector m_SwTraceMessages; + +private: + void ParseData(const armnn::profiling::Packet& packet); + void Print(); + + bool m_QuietOperation; +}; + +} //namespace gatordmock + +} //namespace armnn \ No newline at end of file diff --git a/tests/profiling/timelineDecoder/TimelineModel.h b/tests/profiling/timelineDecoder/TimelineModel.h new file mode 100644 index 0000000000..a4fbd0dbde --- /dev/null +++ b/tests/profiling/timelineDecoder/TimelineModel.h @@ -0,0 +1,96 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// +#ifndef ARMNN_ITIMELINEMODEL_H +#define ARMNN_ITIMELINEMODEL_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +struct Model; + +typedef enum RelationshipType +{ + RetentionLink, /// Head retains(parents) Tail + ExecutionLink, /// Head execution start depends on Tail execution completion + DataLink, /// Head uses data of Tail + LabelLink /// Head uses label Tail (Tail MUST be a guid of a label). +} RelationshipType; + +typedef struct Entity +{ + uint64_t m_Guid; +} Entity; + +typedef struct EventClass +{ + uint64_t m_Guid; +} EventClass; + +typedef struct Event +{ + uint64_t m_Guid; + uint64_t m_TimeStamp; + unsigned char* m_ThreadId; +} ProfilingEvent; + +typedef struct Label +{ + uint64_t m_Guid; + char* m_Name; +} Label; + +typedef struct Relationship +{ + RelationshipType m_RelationshipType; + uint64_t m_Guid; + uint64_t m_HeadGuid; + uint64_t m_TailGuid; +} Relationship; + +typedef void (*OnNewEntityCallback)(const Entity, struct Model* model); +typedef void (*OnNewEventClassCallback)(const EventClass, struct Model* model); +typedef void (*OnNewEventCallback)(const Event, struct Model* model); +typedef void (*OnNewLabelCallback)(const Label, struct Model* model); +typedef void (*OnNewRelationshipCallback)(const Relationship, struct Model* model) ; + +typedef struct Model +{ + OnNewEntityCallback m_EntityCb; + OnNewEventClassCallback m_EventClassCb; + OnNewEventCallback m_EventCb; + OnNewLabelCallback m_LabelCb; + OnNewRelationshipCallback m_RelationshipCb; + + Entity** m_Entities; + EventClass** m_EventClasses; + Event** m_Events; + Label** m_Labels; + Relationship** m_Relationships; + + uint32_t m_EntityCount; + uint32_t m_EntityCapacity; + + uint32_t m_EventClassCount; + uint32_t m_EventClassCapacity; + + uint32_t m_EventCount; + uint32_t m_EventCapacity; + + uint32_t m_LabelCount; + uint32_t m_LabelCapacity; + + uint32_t m_RelationshipCount; + uint32_t m_RelationshipCapacity; +} Model; + +#ifdef __cplusplus +} +#endif + +#endif //ARMNN_ITIMELINEMODEL_H \ No newline at end of file diff --git a/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp b/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp new file mode 100644 index 0000000000..3fd9d04dbc --- /dev/null +++ b/tests/profiling/timelineDecoder/tests/TimelineTestFunctions.hpp @@ -0,0 +1,143 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include +#include "../TimelineModel.h" + +void PushEntity(const Entity entity, Model* model) +{ + if(model->m_EntityCount == 0) + { + model->m_EntityCapacity = 1; + model->m_Entities = new Entity*[model->m_EntityCapacity]; + } + else if(model->m_EntityCount >= model->m_EntityCapacity) + { + Entity** newEntityArray = new Entity*[model->m_EntityCapacity*2]; + + std::copy(model->m_Entities, model->m_Entities + model->m_EntityCapacity, newEntityArray); + delete[] model->m_Entities; + model->m_Entities = newEntityArray; + + model->m_EntityCapacity = model->m_EntityCapacity *2; + } + + Entity* newEntity = new Entity; + + newEntity->m_Guid = entity.m_Guid; + + model->m_Entities[model->m_EntityCount] = newEntity; + model->m_EntityCount++; +}; + +void PushEventClass(const EventClass eventClass, Model* model) +{ + if(model->m_EventClassCount == 0) + { + model->m_EventClassCapacity = 1; + model->m_EventClasses = new EventClass*[model->m_EventClassCapacity]; + } + else if(model->m_EventClassCount >= model->m_EventClassCapacity) + { + EventClass** newEventClassArray = new EventClass*[model->m_EventClassCapacity *2]; + + std::copy(model->m_EventClasses, model->m_EventClasses + model->m_EventClassCapacity, newEventClassArray); + delete[] model->m_EventClasses; + model->m_EventClasses = newEventClassArray; + + model->m_EventClassCapacity = model->m_EventClassCapacity *2; + } + + EventClass* newEventClass = new EventClass; + + newEventClass->m_Guid = eventClass.m_Guid; + + model->m_EventClasses[model->m_EventClassCount] = newEventClass; + model->m_EventClassCount++; +}; + +void PushEvent(const Event event, Model* model) +{ + if(model->m_EventCount == 0) + { + model->m_EventCapacity = 1; + model->m_Events = new Event*[model->m_EventCapacity]; + } + else if(model->m_EventCount >= model->m_EventCapacity) + { + Event** newEventArray = new Event*[model->m_EventCapacity * 2]; + + std::copy(model->m_Events, model->m_Events + model->m_EventCapacity, newEventArray); + delete[] model->m_Events; + model->m_Events = newEventArray; + + model->m_EventCapacity = model->m_EventCapacity *2; + } + + Event* newEvent = new Event; + + newEvent->m_TimeStamp = event.m_TimeStamp; + newEvent->m_ThreadId = event.m_ThreadId; + newEvent->m_Guid = event.m_Guid; + + model->m_Events[model->m_EventCount] = newEvent; + model->m_EventCount++; +}; + +void PushLabel(const Label label, Model* model) +{ + if(model->m_LabelCount == 0) + { + model->m_LabelCapacity = 1; + model->m_Labels = new Label*[model->m_LabelCapacity]; + } + else if(model->m_LabelCount >= model->m_LabelCapacity) + { + Label** newLabelArray = new Label*[model->m_LabelCapacity *2]; + + std::copy(model->m_Labels, model->m_Labels + model->m_LabelCapacity, newLabelArray); + delete[] model->m_Labels; + model->m_Labels = newLabelArray; + + model->m_LabelCapacity = model->m_LabelCapacity *2; + } + + Label* newLabel = new Label; + + newLabel->m_Guid = label.m_Guid; + newLabel->m_Name = label.m_Name; + + model->m_Labels[model->m_LabelCount] = newLabel; + model->m_LabelCount++; +}; + +void PushRelationship(const Relationship relationship, Model* model) +{ + if(model->m_RelationshipCount == 0) + { + model->m_RelationshipCapacity = 1; + model->m_Relationships = new Relationship*[model->m_RelationshipCapacity]; + } + else if(model->m_RelationshipCount >= model->m_RelationshipCapacity) + { + Relationship** newRelationshipArray = new Relationship*[model->m_RelationshipCapacity *2]; + + std::copy(model->m_Relationships, model->m_Relationships + model->m_RelationshipCapacity, newRelationshipArray); + delete[] model->m_Relationships; + model->m_Relationships = newRelationshipArray; + + model->m_RelationshipCapacity = model->m_RelationshipCapacity *2; + } + + Relationship* newRelationship = new Relationship; + + newRelationship->m_Guid = relationship.m_Guid; + newRelationship->m_RelationshipType = relationship.m_RelationshipType; + newRelationship->m_HeadGuid = relationship.m_HeadGuid; + newRelationship->m_TailGuid = relationship.m_TailGuid; + + model->m_Relationships[model->m_RelationshipCount] = newRelationship; + model->m_RelationshipCount++; +}; diff --git a/tests/profiling/timelineDecoder/tests/TimelineTests.cpp b/tests/profiling/timelineDecoder/tests/TimelineTests.cpp new file mode 100644 index 0000000000..a9c352b5fa --- /dev/null +++ b/tests/profiling/timelineDecoder/tests/TimelineTests.cpp @@ -0,0 +1,206 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "../TimelineCaptureCommandHandler.hpp" +#include "../TimelineDirectoryCaptureCommandHandler.hpp" +#include "../ITimelineDecoder.h" +#include "../TimelineModel.h" +#include "TimelineTestFunctions.hpp" + +#include +#include +#include +#include + +#include +#include + +BOOST_AUTO_TEST_SUITE(TimelineDecoderTests) + +using namespace armnn; + +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; + + std::unique_ptr uniquePacketData = std::make_unique(PacketDataLength); + + std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength); + + armnn::profiling::Packet packet = armnn::profiling::Packet(header[0], PacketDataLength, uniquePacketData); + + CommandHandler(packet); +} + +BOOST_AUTO_TEST_CASE(TimelineDirecotryTest) +{ + uint32_t uint32_t_size = sizeof(uint32_t); + + profiling::BufferManager bufferManager(5); + profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + + std::unique_ptr sendTimelinePacket = + timelinePacketWriterFactory.GetSendTimelinePacket(); + + profiling::PacketVersionResolver packetVersionResolver; + + gatordmock::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler( + 1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(), true); + + sendTimelinePacket->SendTimelineMessageDirectoryPackage(); + sendTimelinePacket->Commit(); + + std::vector swTraceBufferMessages; + + unsigned int offset = uint32_t_size * 2; + + std::unique_ptr packetBuffer = bufferManager.GetReadableBuffer(); + + 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.name == handlerMessage.name); + BOOST_CHECK(bufferMessage.uiName == handlerMessage.uiName); + BOOST_CHECK(bufferMessage.id == handlerMessage.id); + + BOOST_CHECK(bufferMessage.argTypes.size() == handlerMessage.argTypes.size()); + for(uint32_t i = 0; i < bufferMessage.argTypes.size(); ++i) + { + BOOST_CHECK(bufferMessage.argTypes[i] == handlerMessage.argTypes[i]); + } + + BOOST_CHECK(bufferMessage.argNames.size() == handlerMessage.argNames.size()); + for(uint32_t i = 0; i < bufferMessage.argNames.size(); ++i) + { + BOOST_CHECK(bufferMessage.argNames[i] == handlerMessage.argNames[i]); + } + } +} + +BOOST_AUTO_TEST_CASE(TimelineCaptureTest) +{ + uint32_t threadId_size = sizeof(std::thread::id); + + profiling::BufferManager bufferManager(50); + profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + + std::unique_ptr sendTimelinePacket = + timelinePacketWriterFactory.GetSendTimelinePacket(); + + profiling::PacketVersionResolver packetVersionResolver; + + Model* modelPtr; + CreateModel(&modelPtr); + + gatordmock::TimelineCaptureCommandHandler timelineCaptureCommandHandler( + 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), modelPtr, true); + + BOOST_CHECK(SetEntityCallback(PushEntity, modelPtr) == ErrorCode_Success); + BOOST_CHECK(SetEventClassCallback(PushEventClass, modelPtr) == ErrorCode_Success); + BOOST_CHECK(SetEventCallback(PushEvent, modelPtr) == ErrorCode_Success); + BOOST_CHECK(SetLabelCallback(PushLabel, modelPtr) == ErrorCode_Success); + BOOST_CHECK(SetRelationshipCallback(PushRelationship, modelPtr) == ErrorCode_Success); + + const uint64_t entityGuid = 22222u; + + const uint64_t eventClassGuid = 33333u; + + const uint64_t timestamp = 111111u; + const uint64_t eventGuid = 55555u; + + const std::thread::id threadId = std::this_thread::get_id();; + + const uint64_t labelGuid = 11111u; + std::string labelName = "test_label"; + + const uint64_t relationshipGuid = 44444u; + const uint64_t headGuid = 111111u; + const uint64_t tailGuid = 222222u; + + 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 (int i = 0; i < 10; ++i) + { + BOOST_CHECK(modelPtr->m_Entities[i]->m_Guid == entityGuid); + + BOOST_CHECK(modelPtr->m_EventClasses[i]->m_Guid == eventClassGuid); + + BOOST_CHECK(modelPtr->m_Events[i]->m_TimeStamp == timestamp); + + std::vector readThreadId(threadId_size, 0); + profiling::ReadBytes(modelPtr->m_Events[i]->m_ThreadId, 0, threadId_size, readThreadId.data()); + BOOST_CHECK(readThreadId == threadId); + + BOOST_CHECK(modelPtr->m_Events[i]->m_Guid == eventGuid); + + BOOST_CHECK(modelPtr->m_Labels[i]->m_Guid == labelGuid); + BOOST_CHECK(std::string(modelPtr->m_Labels[i]->m_Name) == labelName); + + BOOST_CHECK(modelPtr->m_Relationships[i]->m_RelationshipType == RelationshipType::DataLink); + BOOST_CHECK(modelPtr->m_Relationships[i]->m_Guid == relationshipGuid); + BOOST_CHECK(modelPtr->m_Relationships[i]->m_HeadGuid == headGuid); + BOOST_CHECK(modelPtr->m_Relationships[i]->m_TailGuid == tailGuid); + } + + DestroyModel(&modelPtr); +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1