IVGCVSW-4035 Add a CreateTypedLabel function
authorMatteo Martincigh <matteo.martincigh@arm.com>
Mon, 28 Oct 2019 15:24:34 +0000 (15:24 +0000)
committerMatteo Martincigh <matteo.martincigh@arm.com>
Wed, 30 Oct 2019 09:55:44 +0000 (09:55 +0000)
 * Create new utility function in the TimelineUtilityMethods class
 * Added unit tests

Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
Change-Id: I63704b94d5cc6861e4e160de2aae4ae497699dd2

src/profiling/TimelineUtilityMethods.cpp
src/profiling/TimelineUtilityMethods.hpp
src/profiling/test/TimelineUtilityMethodsTests.cpp

index aa9f5a5..b34b70f 100644 (file)
@@ -52,6 +52,39 @@ ProfilingStaticGuid TimelineUtilityMethods::DeclareLabel(const std::string& labe
     return labelGuid;
 }
 
+void TimelineUtilityMethods::CreateTypedLabel(ProfilingGuid entityGuid,
+                                              const std::string& entityName,
+                                              ProfilingStaticGuid labelTypeGuid)
+{
+    // Check that the entity name is valid
+    if (entityName.empty())
+    {
+        // The entity name is invalid
+        throw InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
+    }
+
+    // Declare a label with the entity's name, this call throws in case of error
+    ProfilingGuid labelGuid = DeclareLabel(entityName);
+
+    // Generate a GUID for the label relationship
+    ProfilingGuid relationshipGuid = ProfilingService::Instance().NextGuid();
+
+    // Send the new label link to the external profiling service, this call throws in case of error
+    m_SendTimelinePacket.SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
+                                                              relationshipGuid,
+                                                              entityGuid,
+                                                              labelGuid);
+
+    // Generate a GUID for the label relationship
+    ProfilingGuid relationshipLabelGuid = ProfilingService::Instance().NextGuid();
+
+    // Send the new label link to the external profiling service, this call throws in case of error
+    m_SendTimelinePacket.SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
+                                                              relationshipLabelGuid,
+                                                              relationshipGuid,
+                                                              labelTypeGuid);
+}
+
 } // namespace profiling
 
 } // namespace armnn
index f3e925e..63e5c40 100644 (file)
@@ -25,6 +25,7 @@ public:
     void SendWellKnownLabelsAndEventClasses();
 
     ProfilingStaticGuid DeclareLabel(const std::string& labelName);
+    void CreateTypedLabel(ProfilingGuid entityGuid, const std::string& entityName, ProfilingStaticGuid labelTypeGuid);
 
 private:
     ISendTimelinePacket& m_SendTimelinePacket;
index 6d0fa2e..c98ed83 100644 (file)
@@ -8,6 +8,7 @@
 #include <SendTimelinePacket.hpp>
 #include <TimelineUtilityMethods.hpp>
 #include <LabelsAndEventClasses.hpp>
+#include <ProfilingService.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -30,7 +31,7 @@ inline unsigned int OffsetToNextWord(unsigned int numberOfBytes)
     return numberOfBytes + uint32_t_size - remainder;
 }
 
-void VerifyTimelineLabelBinaryPacket(ProfilingGuid guid,
+void VerifyTimelineLabelBinaryPacket(Optional<ProfilingGuid> guid,
                                      const std::string& label,
                                      const unsigned char* readableData,
                                      unsigned int& offset)
@@ -67,7 +68,14 @@ void VerifyTimelineLabelBinaryPacket(ProfilingGuid guid,
     // Check the profiling GUID
     offset += uint32_t_size;
     uint64_t readProfilingGuid = ReadUint64(readableData, offset);
-    BOOST_CHECK(readProfilingGuid == guid);
+    if (guid.has_value())
+    {
+        BOOST_CHECK(readProfilingGuid == guid.value());
+    }
+    else
+    {
+        BOOST_CHECK(readProfilingGuid == ProfilingService::Instance().GenerateStaticId(label));
+    }
 
     // Check the SWTrace label
     offset += uint64_t_size;
@@ -120,6 +128,106 @@ void VerifyTimelineEventClassBinaryPacket(ProfilingGuid guid,
     uint64_t readProfilingGuid = ReadUint64(readableData, offset);
     BOOST_CHECK(readProfilingGuid == guid);
 
+    // Update the offset to allow parsing to be continued after this function returns
+    offset += uint64_t_size;
+}
+
+void VerifyTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                            Optional<ProfilingGuid> relationshipGuid,
+                                            Optional<ProfilingGuid> headGuid,
+                                            Optional<ProfilingGuid> tailGuid,
+                                            const unsigned char* readableData,
+                                            unsigned int& offset)
+{
+    BOOST_ASSERT(readableData);
+
+    uint32_t relationshipTypeUint = 0;
+    switch (relationshipType)
+    {
+        case ProfilingRelationshipType::RetentionLink:
+            relationshipTypeUint = 0;
+            break;
+        case ProfilingRelationshipType::ExecutionLink:
+            relationshipTypeUint = 1;
+            break;
+        case ProfilingRelationshipType::DataLink:
+            relationshipTypeUint = 2;
+            break;
+        case ProfilingRelationshipType::LabelLink:
+            relationshipTypeUint = 3;
+            break;
+        default:
+            BOOST_ERROR("Unknown relationship type");
+    }
+
+    // Utils
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the TimelineLabelBinaryPacket header
+    uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(readableData, offset);
+    uint32_t entityBinaryPacketFamily      = (entityBinaryPacketHeaderWord0 >> 26) & 0x0000003F;
+    uint32_t entityBinaryPacketClass       = (entityBinaryPacketHeaderWord0 >> 19) & 0x0000007F;
+    uint32_t entityBinaryPacketType        = (entityBinaryPacketHeaderWord0 >> 16) & 0x00000007;
+    uint32_t entityBinaryPacketStreamId    = (entityBinaryPacketHeaderWord0 >>  0) & 0x00000007;
+    BOOST_CHECK(entityBinaryPacketFamily   == 1);
+    BOOST_CHECK(entityBinaryPacketClass    == 0);
+    BOOST_CHECK(entityBinaryPacketType     == 1);
+    BOOST_CHECK(entityBinaryPacketStreamId == 0);
+    offset += uint32_t_size;
+    uint32_t entityBinaryPacketHeaderWord1   = ReadUint32(readableData, offset);
+    uint32_t eventBinaryPacketSequenceNumber = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t eventBinaryPacketDataLength     = (entityBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(eventBinaryPacketSequenceNumber == 0);
+    BOOST_CHECK(eventBinaryPacketDataLength     == 32);
+
+    // Check the decl id
+    offset += uint32_t_size;
+    uint32_t eventClassDeclId = ReadUint32(readableData, offset);
+    BOOST_CHECK(eventClassDeclId == 3);
+
+    // Check the relationship type
+    offset += uint32_t_size;
+    uint32_t readRelationshipTypeUint = ReadUint32(readableData, offset);
+    BOOST_CHECK(readRelationshipTypeUint == relationshipTypeUint);
+
+    // Check the relationship GUID
+    offset += uint32_t_size;
+    uint64_t readRelationshipGuid = ReadUint64(readableData, offset);
+    if (relationshipGuid.has_value())
+    {
+        BOOST_CHECK(readRelationshipGuid == relationshipGuid.value());
+    }
+    else
+    {
+        BOOST_CHECK(readRelationshipGuid != ProfilingGuid(0));
+    }
+
+    // Check the head of relationship GUID
+    offset += uint64_t_size;
+    uint64_t readHeadRelationshipGuid = ReadUint64(readableData, offset);
+    if (headGuid.has_value())
+    {
+        BOOST_CHECK(readHeadRelationshipGuid == headGuid.value());
+    }
+    else
+    {
+        BOOST_CHECK(readHeadRelationshipGuid != ProfilingGuid(0));
+    }
+
+    // Check the tail of relationship GUID
+    offset += uint64_t_size;
+    uint64_t readTailRelationshipGuid = ReadUint64(readableData, offset);
+    if (tailGuid.has_value())
+    {
+        BOOST_CHECK(readTailRelationshipGuid == tailGuid.value());
+    }
+    else
+    {
+        BOOST_CHECK(readTailRelationshipGuid != ProfilingGuid(0));
+    }
+
+    // Update the offset to allow parsing to be continued after this function returns
     offset += uint64_t_size;
 }
 
@@ -127,6 +235,55 @@ void VerifyTimelineEventClassBinaryPacket(ProfilingGuid guid,
 
 BOOST_AUTO_TEST_SUITE(TimelineUtilityMethodsTests)
 
+BOOST_AUTO_TEST_CASE(CreateTypedLabelTest)
+{
+    MockBufferManager mockBufferManager(1024);
+    SendTimelinePacket sendTimelinePacket(mockBufferManager);
+    TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
+
+    ProfilingGuid entityGuid(123);
+    const std::string entityName = "some entity";
+    ProfilingStaticGuid labelTypeGuid(456);
+
+    BOOST_CHECK_NO_THROW(timelineUtilityMethods.CreateTypedLabel(entityGuid, entityName, labelTypeGuid));
+
+    // Commit all packets at once
+    sendTimelinePacket.Commit();
+
+    // Get the readable buffer
+    auto readableBuffer = mockBufferManager.GetReadableBuffer();
+    BOOST_CHECK(readableBuffer != nullptr);
+    unsigned int size = readableBuffer->GetSize();
+    BOOST_CHECK(size == 116);
+    const unsigned char* readableData = readableBuffer->GetReadableData();
+    BOOST_CHECK(readableData != nullptr);
+
+    // Utils
+    unsigned int offset = 0;
+
+    // First packet sent: TimelineLabelBinaryPacket
+    VerifyTimelineLabelBinaryPacket(EmptyOptional(), entityName, readableData, offset);
+
+    // Second packet sent: TimelineRelationshipBinaryPacket
+    VerifyTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
+                                           EmptyOptional(),
+                                           entityGuid,
+                                           EmptyOptional(),
+                                           readableData,
+                                           offset);
+
+    // Third packet sent: TimelineRelationshipBinaryPacket
+    VerifyTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
+                                           EmptyOptional(),
+                                           EmptyOptional(),
+                                           labelTypeGuid,
+                                           readableData,
+                                           offset);
+
+    // Mark the buffer as read
+    mockBufferManager.MarkRead(readableBuffer);
+}
+
 BOOST_AUTO_TEST_CASE(SendWellKnownLabelsAndEventClassesTest)
 {
     MockBufferManager mockBufferManager(1024);