IVGCVSW-3950 Create SendTimelinePacket interface and class

* Implemented ISendTimelinePacket interface and its implementation SendTimelinePacket
* Implemented TimelinePacketWriterFactory
* Implemented unit tests for SendTimelinePacket functions

Signed-off-by: Sadik Armagan <sadik.armagan@arm.com>
Change-Id: I0a47586437f99510394d4d94589dccfb397d38e5
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d686d3f..e3b1f8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -455,6 +455,7 @@
     src/profiling/ICounterDirectory.hpp
     src/profiling/ICounterValues.hpp
     src/profiling/ISendCounterPacket.hpp
+    src/profiling/ISendTimelinePacket.hpp
     src/profiling/IPacketBuffer.hpp
     src/profiling/IPeriodicCounterCapture.hpp
     src/profiling/IProfilingConnection.hpp
@@ -486,8 +487,12 @@
     src/profiling/RequestCounterDirectoryCommandHandler.hpp
     src/profiling/SendCounterPacket.cpp
     src/profiling/SendCounterPacket.hpp
+    src/profiling/SendTimelinePacket.cpp
+    src/profiling/SendTimelinePacket.hpp
     src/profiling/SocketProfilingConnection.cpp
     src/profiling/SocketProfilingConnection.hpp
+    src/profiling/TimelinePacketWriterFactory.cpp
+    src/profiling/TimelinePacketWriterFactory.hpp
     third-party/half/half.hpp
     )
 
@@ -616,6 +621,7 @@
         src/profiling/test/ProfilingTests.hpp
         src/profiling/test/SendCounterPacketTests.cpp
         src/profiling/test/SendCounterPacketTests.hpp
+        src/profiling/test/SendTimelinePacketTests.cpp
         src/profiling/test/TimelinePacketTests.cpp
         )
 
diff --git a/src/profiling/IBufferManager.hpp b/src/profiling/IBufferManager.hpp
index 0acdf61..c35d9c6 100644
--- a/src/profiling/IBufferManager.hpp
+++ b/src/profiling/IBufferManager.hpp
@@ -9,6 +9,8 @@
 
 #include <memory>
 
+#define MAX_METADATA_PACKET_LENGTH 4096
+
 namespace armnn
 {
 
diff --git a/src/profiling/ISendTimelinePacket.hpp b/src/profiling/ISendTimelinePacket.hpp
new file mode 100644
index 0000000..34157b8
--- /dev/null
+++ b/src/profiling/ISendTimelinePacket.hpp
@@ -0,0 +1,53 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "ProfilingUtils.hpp"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class ISendTimelinePacket
+{
+public:
+    virtual ~ISendTimelinePacket() {}
+
+    /// Commits the current buffer and reset the member variables
+    virtual void Commit() = 0;
+
+    /// Create and write a TimelineEntityBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineEntityBinaryPacket(uint64_t profilingGuid) = 0;
+
+    /// Create and write a TimelineEventBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid) = 0;
+
+    /// Create and write a TimelineEventClassBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineEventClassBinaryPacket(uint64_t profilingGuid) = 0;
+
+    /// Create and write a TimelineLabelBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) = 0;
+
+    /// Create and write a TimelineMessageDirectoryPackage in the buffer
+    virtual void SendTimelineMessageDirectoryPackage() = 0;
+
+    /// Create and write a TimelineRelationshipBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                                      uint64_t relationshipGuid,
+                                                      uint64_t headGuid,
+                                                      uint64_t tailGuid) = 0;
+};
+
+} // namespace profiling
+
+} // namespace armnn
+
diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp
index f4d4f8f..905ecb5 100644
--- a/src/profiling/ProfilingUtils.cpp
+++ b/src/profiling/ProfilingUtils.cpp
@@ -279,6 +279,91 @@
     return std::make_pair(packetHeaderWord0, packetHeaderWord1);
 }
 
+// Calculate the actual length an SwString will be including the terminating null character
+// padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding
+// the size to allow the offset to be correctly updated when decoding a binary packet.
+uint32_t CalculateSizeOfPaddedSwString(const std::string& str)
+{
+    std::vector<uint32_t> swTraceString;
+    StringToSwTraceString<SwTraceCharPolicy>(str, swTraceString);
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    uint32_t size = (boost::numeric_cast<uint32_t>(swTraceString.size()) - 1) * uint32_t_size;
+    return size;
+}
+
+// Read TimelineMessageDirectoryPacket from given IPacketBuffer and offset
+SwTraceMessage ReadSwTraceMessage(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int& offset)
+{
+    BOOST_ASSERT(packetBuffer);
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+
+    SwTraceMessage swTraceMessage;
+
+    // Read the decl_id
+    uint32_t readDeclId = ReadUint32(packetBuffer, offset);
+    swTraceMessage.id = readDeclId;
+
+    // SWTrace "namestring" format
+    // length of the string (first 4 bytes) + string + null terminator
+
+    // Check the decl_name
+    offset += uint32_t_size;
+    uint32_t swTraceDeclNameLength = ReadUint32(packetBuffer, offset);
+
+    offset += uint32_t_size;
+    std::vector<unsigned char> swTraceStringBuffer(swTraceDeclNameLength - 1);
+    std::memcpy(swTraceStringBuffer.data(),
+                packetBuffer->GetReadableData()  + offset, swTraceStringBuffer.size());
+
+    swTraceMessage.name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name
+
+    // Check the ui_name
+    offset += CalculateSizeOfPaddedSwString(swTraceMessage.name);
+    uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset);
+
+    offset += uint32_t_size;
+    swTraceStringBuffer.resize(swTraceUINameLength - 1);
+    std::memcpy(swTraceStringBuffer.data(),
+                packetBuffer->GetReadableData()  + offset, swTraceStringBuffer.size());
+
+    swTraceMessage.uiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name
+
+    // Check arg_types
+    offset += CalculateSizeOfPaddedSwString(swTraceMessage.uiName);
+    uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset);
+
+    offset += uint32_t_size;
+    swTraceStringBuffer.resize(swTraceArgTypesLength - 1);
+    std::memcpy(swTraceStringBuffer.data(),
+                packetBuffer->GetReadableData()  + offset, swTraceStringBuffer.size());
+
+    swTraceMessage.argTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types
+
+    std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
+
+    // Check arg_names
+    offset += CalculateSizeOfPaddedSwString(swTraceString);
+    uint32_t swTraceArgNamesLength = ReadUint32(packetBuffer, offset);
+
+    offset += uint32_t_size;
+    swTraceStringBuffer.resize(swTraceArgNamesLength - 1);
+    std::memcpy(swTraceStringBuffer.data(),
+                packetBuffer->GetReadableData()  + offset, swTraceStringBuffer.size());
+
+    swTraceString.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end());
+    std::stringstream stringStream(swTraceString);
+    std::string argName;
+    while (std::getline(stringStream, argName, ','))
+    {
+        swTraceMessage.argNames.push_back(argName);
+    }
+
+    offset += CalculateSizeOfPaddedSwString(swTraceString);
+
+    return swTraceMessage;
+}
+
 /// Creates a packet header for the timeline messages:
 /// * declareLabel
 /// * declareEntity
diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp
index 582f7c4..777711a 100644
--- a/src/profiling/ProfilingUtils.hpp
+++ b/src/profiling/ProfilingUtils.hpp
@@ -23,6 +23,15 @@
 namespace profiling
 {
 
+struct SwTraceMessage
+{
+    uint32_t id;
+    std::string name;
+    std::string uiName;
+    std::vector<char> argTypes;
+    std::vector<std::string> argNames;
+};
+
 struct SwTraceCharPolicy
 {
     static bool IsValidChar(unsigned char c)
@@ -134,6 +143,10 @@
     LabelLink      /// Head uses label Tail (Tail MUST be a guid of a label).
 };
 
+uint32_t CalculateSizeOfPaddedSwString(const std::string& str);
+
+SwTraceMessage ReadSwTraceMessage(const std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int& offset);
+
 TimelinePacketStatus WriteTimelineLabelBinaryPacket(uint64_t profilingGuid,
                                                     const std::string& label,
                                                     unsigned char* buffer,
diff --git a/src/profiling/SendCounterPacket.cpp b/src/profiling/SendCounterPacket.cpp
index 0ac6ecf..382f958 100644
--- a/src/profiling/SendCounterPacket.cpp
+++ b/src/profiling/SendCounterPacket.cpp
@@ -25,7 +25,6 @@
 using boost::numeric_cast;
 
 const unsigned int SendCounterPacket::PIPE_MAGIC;
-const unsigned int SendCounterPacket::MAX_METADATA_PACKET_LENGTH;
 
 void SendCounterPacket::SendStreamMetaDataPacket()
 {
diff --git a/src/profiling/SendCounterPacket.hpp b/src/profiling/SendCounterPacket.hpp
index e1a42aa..2aaabc8 100644
--- a/src/profiling/SendCounterPacket.hpp
+++ b/src/profiling/SendCounterPacket.hpp
@@ -59,7 +59,6 @@
     void SetReadyToRead() override;
 
     static const unsigned int PIPE_MAGIC = 0x45495434;
-    static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096;
 
     void Start(IProfilingConnection& profilingConnection);
     void Stop(bool rethrowSendThreadExceptions = true);
diff --git a/src/profiling/SendTimelinePacket.cpp b/src/profiling/SendTimelinePacket.cpp
new file mode 100644
index 0000000..e6e5ee7
--- /dev/null
+++ b/src/profiling/SendTimelinePacket.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SendTimelinePacket.hpp"
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+void SendTimelinePacket::Commit()
+{
+    if (m_WriteBuffer != nullptr)
+    {
+        // Commit the message
+        m_BufferManager.Commit(m_WriteBuffer, m_Offset);
+        m_WriteBuffer.reset(nullptr);
+        m_Offset = 0;
+        m_BufferSize = 0;
+    }
+}
+
+void SendTimelinePacket::ReserveBuffer()
+{
+    if (m_WriteBuffer == nullptr)
+    {
+        uint32_t reserved = 0;
+
+        // Reserve the buffer
+        m_WriteBuffer = m_BufferManager.Reserve(MAX_METADATA_PACKET_LENGTH, reserved);
+
+        // Check if there is enough space in the buffer
+        if (m_WriteBuffer == nullptr || reserved < m_Offset)
+        {
+            throw RuntimeException("No space left on buffer", CHECK_LOCATION());
+        }
+        m_BufferSize = reserved;
+    }
+}
+
+#define FORWARD_WRITE_BINARY_FUNC(func, ...) \
+try \
+{ \
+   ReserveBuffer(); \
+   unsigned int numberOfBytes = 0; \
+   while (1) \
+   { \
+      TimelinePacketStatus result = func(__VA_ARGS__, numberOfBytes); \
+      if (result == armnn::profiling::TimelinePacketStatus::BufferExhaustion) \
+      { \
+         Commit(); \
+         ReserveBuffer(); \
+      } \
+      else if (result == armnn::profiling::TimelinePacketStatus::Error) \
+      { \
+         throw RuntimeException("Error processing while sending TimelineBinaryPacket.", CHECK_LOCATION()); \
+      } \
+      else \
+      { \
+         break; \
+      } \
+    } \
+    m_Offset     += numberOfBytes; \
+    m_BufferSize -= numberOfBytes; \
+} \
+catch(...) \
+{ \
+   throw RuntimeException("Error processing while sending TimelineBinaryPacket.", CHECK_LOCATION()); \
+}
+
+void SendTimelinePacket::SendTimelineEntityBinaryPacket(uint64_t profilingGuid)
+{
+    FORWARD_WRITE_BINARY_FUNC(WriteTimelineEntityBinaryPacket,
+                              profilingGuid,
+                              &m_WriteBuffer->GetWritableData()[m_Offset],
+                              m_BufferSize);
+}
+
+void SendTimelinePacket::SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid)
+{
+    FORWARD_WRITE_BINARY_FUNC(WriteTimelineEventBinaryPacket,
+                              timestamp,
+                              threadId,
+                              profilingGuid,
+                              &m_WriteBuffer->GetWritableData()[m_Offset],
+                              m_BufferSize);
+}
+
+void SendTimelinePacket::SendTimelineEventClassBinaryPacket(uint64_t profilingGuid)
+{
+    FORWARD_WRITE_BINARY_FUNC(WriteTimelineEventClassBinaryPacket,
+                              profilingGuid,
+                              &m_WriteBuffer->GetWritableData()[m_Offset],
+                              m_BufferSize);
+}
+
+void SendTimelinePacket::SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label)
+{
+    FORWARD_WRITE_BINARY_FUNC(WriteTimelineLabelBinaryPacket,
+                              profilingGuid,
+                              label,
+                              &m_WriteBuffer->GetWritableData()[m_Offset],
+                              m_BufferSize);
+}
+
+void SendTimelinePacket::SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                                              uint64_t relationshipGuid,
+                                                              uint64_t headGuid,
+                                                              uint64_t tailGuid)
+{
+    FORWARD_WRITE_BINARY_FUNC(WriteTimelineRelationshipBinaryPacket,
+                              relationshipType,
+                              relationshipGuid,
+                              headGuid,
+                              tailGuid,
+                              &m_WriteBuffer->GetWritableData()[m_Offset],
+                              m_BufferSize);
+}
+
+void SendTimelinePacket::SendTimelineMessageDirectoryPackage()
+{
+    try
+    {
+        // Reserve buffer if hasn't already reserved
+        ReserveBuffer();
+
+        unsigned int numberOfBytes = 0;
+        // Write to buffer
+        TimelinePacketStatus result = WriteTimelineMessageDirectoryPackage(&m_WriteBuffer->GetWritableData()[m_Offset],
+                                                                           m_BufferSize,
+                                                                           numberOfBytes);
+
+        if (result != armnn::profiling::TimelinePacketStatus::Ok)
+        {
+            throw RuntimeException("Error processing TimelineMessageDirectoryPackage.", CHECK_LOCATION());
+        }
+
+        // Commit the message
+        m_Offset     += numberOfBytes;
+        m_BufferSize -= numberOfBytes;
+        m_BufferManager.Commit(m_WriteBuffer, m_Offset);
+    }
+    catch(...)
+    {
+        throw RuntimeException("Error processing TimelineMessageDirectoryPackage.", CHECK_LOCATION());
+    }
+}
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/SendTimelinePacket.hpp b/src/profiling/SendTimelinePacket.hpp
new file mode 100644
index 0000000..35ec24f
--- /dev/null
+++ b/src/profiling/SendTimelinePacket.hpp
@@ -0,0 +1,65 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "IBufferManager.hpp"
+#include "ISendTimelinePacket.hpp"
+#include "ProfilingUtils.hpp"
+
+#include <memory>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class SendTimelinePacket : public ISendTimelinePacket
+{
+public:
+    SendTimelinePacket(IBufferManager& bufferManager)
+      : m_BufferManager(bufferManager)
+      , m_WriteBuffer(nullptr)
+      , m_Offset(0u)
+      , m_BufferSize(0u)
+    {}
+
+    /// Commits the current buffer and reset the member variables
+    void Commit() override;
+
+    /// Create and write a TimelineEntityBinaryPacket from the parameters to the buffer.
+    void SendTimelineEntityBinaryPacket(uint64_t profilingGuid) override;
+
+    /// Create and write a TimelineEventBinaryPacket from the parameters to the buffer.
+    void SendTimelineEventBinaryPacket(uint64_t timestamp, uint32_t threadId, uint64_t profilingGuid) override;
+
+    /// Create and write a TimelineEventClassBinaryPacket from the parameters to the buffer.
+    void SendTimelineEventClassBinaryPacket(uint64_t profilingGuid) override;
+
+    /// Create and write a TimelineLabelBinaryPacket from the parameters to the buffer.
+    void SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) override;
+
+    /// Create and write a TimelineMessageDirectoryPackage in the buffer
+    void SendTimelineMessageDirectoryPackage() override;
+
+    /// Create and write a TimelineRelationshipBinaryPacket from the parameters to the buffer.
+    virtual void SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
+                                                      uint64_t relationshipGuid,
+                                                      uint64_t headGuid,
+                                                      uint64_t tailGuid) override;
+private:
+    /// Reserves maximum packet size from buffer
+    void ReserveBuffer();
+
+    IBufferManager& m_BufferManager;
+    std::unique_ptr<IPacketBuffer> m_WriteBuffer;
+    unsigned int m_Offset;
+    unsigned int m_BufferSize;
+};
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/TimelinePacketWriterFactory.cpp b/src/profiling/TimelinePacketWriterFactory.cpp
new file mode 100644
index 0000000..b1de629
--- /dev/null
+++ b/src/profiling/TimelinePacketWriterFactory.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "TimelinePacketWriterFactory.hpp"
+
+#include "SendTimelinePacket.hpp"
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+std::unique_ptr<ISendTimelinePacket> TimelinePacketWriterFactory::GetSendTimelinePacket() const
+{
+    return std::make_unique<SendTimelinePacket>(m_BufferManager);
+}
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/TimelinePacketWriterFactory.hpp b/src/profiling/TimelinePacketWriterFactory.hpp
new file mode 100644
index 0000000..1bbd3fd
--- /dev/null
+++ b/src/profiling/TimelinePacketWriterFactory.hpp
@@ -0,0 +1,32 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "IBufferManager.hpp"
+#include "ISendTimelinePacket.hpp"
+
+#include <memory>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class TimelinePacketWriterFactory
+{
+public:
+    TimelinePacketWriterFactory(IBufferManager& bufferManager) : m_BufferManager(bufferManager) {}
+
+    std::unique_ptr<ISendTimelinePacket> GetSendTimelinePacket() const;
+
+private:
+    IBufferManager& m_BufferManager;
+};
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/test/SendCounterPacketTests.cpp b/src/profiling/test/SendCounterPacketTests.cpp
index f0ba347..b33b62f 100644
--- a/src/profiling/test/SendCounterPacketTests.cpp
+++ b/src/profiling/test/SendCounterPacketTests.cpp
@@ -5,8 +5,8 @@
 
 #include "SendCounterPacketTests.hpp"
 
-#include <CounterDirectory.hpp>
 #include <BufferManager.hpp>
+#include <CounterDirectory.hpp>
 #include <EncodeVersion.hpp>
 #include <ProfilingUtils.hpp>
 #include <SendCounterPacket.hpp>
@@ -318,7 +318,7 @@
     offset += sizeUint32;
     BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version
     offset += sizeUint32;
-    BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::MAX_METADATA_PACKET_LENGTH); // max_data_len
+    BOOST_TEST(ReadUint32(readBuffer2, offset) == MAX_METADATA_PACKET_LENGTH); // max_data_len
     offset += sizeUint32;
     BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast<uint32_t>(getpid())); // pid
     offset += sizeUint32;
diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp
new file mode 100644
index 0000000..6f90106
--- /dev/null
+++ b/src/profiling/test/SendTimelinePacketTests.cpp
@@ -0,0 +1,387 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SendCounterPacketTests.hpp"
+
+#include <BufferManager.hpp>
+#include <ProfilingUtils.hpp>
+#include <SendTimelinePacket.hpp>
+#include <TimelinePacketWriterFactory.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+using namespace armnn::profiling;
+
+BOOST_AUTO_TEST_SUITE(SendTimelinePacketTests)
+
+BOOST_AUTO_TEST_CASE(SendTimelineMessageDirectoryPackageTest)
+{
+    MockBufferManager mockBuffer(512);
+    TimelinePacketWriterFactory timelinePacketWriterFactory(mockBuffer);
+    std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket();
+
+    sendTimelinePacket->SendTimelineMessageDirectoryPackage();
+
+    // Get the readable buffer
+    auto packetBuffer = mockBuffer.GetReadableBuffer();
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    // Check the packet header
+    unsigned int offset = 0;
+    uint32_t packetHeaderWord0 = ReadUint32(packetBuffer, offset);
+    uint32_t packetFamily = (packetHeaderWord0 >> 26) & 0x0000003F;
+    uint32_t packetClass  = (packetHeaderWord0 >> 19) & 0x0000007F;
+    uint32_t packetType   = (packetHeaderWord0 >> 16) & 0x00000007;
+    uint32_t streamId     = (packetHeaderWord0 >>  0) & 0x00000007;
+
+    BOOST_CHECK(packetFamily == 1);
+    BOOST_CHECK(packetClass  == 0);
+    BOOST_CHECK(packetType   == 0);
+    BOOST_CHECK(streamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t packetHeaderWord1 = ReadUint32(packetBuffer, offset);
+    uint32_t sequenceNumbered = (packetHeaderWord1 >> 24) & 0x00000001;
+    uint32_t dataLength       = (packetHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(sequenceNumbered ==  0);
+    BOOST_CHECK(dataLength       == 416);
+
+    offset += uint32_t_size;
+    SwTraceMessage swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+
+    BOOST_CHECK(swTraceMessage.id == 0);
+    BOOST_CHECK(swTraceMessage.name == "declareLabel");
+    BOOST_CHECK(swTraceMessage.uiName == "declare label");
+    BOOST_CHECK(swTraceMessage.argTypes.size() == 2);
+    BOOST_CHECK(swTraceMessage.argTypes[0] == 'p');
+    BOOST_CHECK(swTraceMessage.argTypes[1] == 's');
+    BOOST_CHECK(swTraceMessage.argNames.size() == 2);
+    BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
+    BOOST_CHECK(swTraceMessage.argNames[1] == "value");
+
+    swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+
+    BOOST_CHECK(swTraceMessage.id == 1);
+    BOOST_CHECK(swTraceMessage.name == "declareEntity");
+    BOOST_CHECK(swTraceMessage.uiName == "declare entity");
+    BOOST_CHECK(swTraceMessage.argTypes.size() == 1);
+    BOOST_CHECK(swTraceMessage.argTypes[0] == 'p');
+    BOOST_CHECK(swTraceMessage.argNames.size() == 1);
+    BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
+
+    swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+
+    BOOST_CHECK(swTraceMessage.id == 2);
+    BOOST_CHECK(swTraceMessage.name == "declareEventClass");
+    BOOST_CHECK(swTraceMessage.uiName == "declare event class");
+    BOOST_CHECK(swTraceMessage.argTypes.size() == 1);
+    BOOST_CHECK(swTraceMessage.argTypes[0] == 'p');
+    BOOST_CHECK(swTraceMessage.argNames.size() == 1);
+    BOOST_CHECK(swTraceMessage.argNames[0] == "guid");
+
+    swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+
+    BOOST_CHECK(swTraceMessage.id == 3);
+    BOOST_CHECK(swTraceMessage.name == "declareRelationship");
+    BOOST_CHECK(swTraceMessage.uiName == "declare relationship");
+    BOOST_CHECK(swTraceMessage.argTypes.size() == 4);
+    BOOST_CHECK(swTraceMessage.argTypes[0] == 'I');
+    BOOST_CHECK(swTraceMessage.argTypes[1] == 'p');
+    BOOST_CHECK(swTraceMessage.argTypes[2] == 'p');
+    BOOST_CHECK(swTraceMessage.argTypes[3] == 'p');
+    BOOST_CHECK(swTraceMessage.argNames.size() == 4);
+    BOOST_CHECK(swTraceMessage.argNames[0] == "relationshipType");
+    BOOST_CHECK(swTraceMessage.argNames[1] == "relationshipGuid");
+    BOOST_CHECK(swTraceMessage.argNames[2] == "headGuid");
+    BOOST_CHECK(swTraceMessage.argNames[3] == "tailGuid");
+
+    swTraceMessage = ReadSwTraceMessage(packetBuffer, offset);
+
+    BOOST_CHECK(swTraceMessage.id == 4);
+    BOOST_CHECK(swTraceMessage.name == "declareEvent");
+    BOOST_CHECK(swTraceMessage.uiName == "declare event");
+    BOOST_CHECK(swTraceMessage.argTypes.size() == 3);
+    BOOST_CHECK(swTraceMessage.argTypes[0] == '@');
+    BOOST_CHECK(swTraceMessage.argTypes[1] == 't');
+    BOOST_CHECK(swTraceMessage.argTypes[2] == 'p');
+    BOOST_CHECK(swTraceMessage.argNames.size() == 3);
+    BOOST_CHECK(swTraceMessage.argNames[0] == "timestamp");
+    BOOST_CHECK(swTraceMessage.argNames[1] == "threadId");
+    BOOST_CHECK(swTraceMessage.argNames[2] == "eventGuid");
+}
+
+BOOST_AUTO_TEST_CASE(SendTimelineEntityPlusEventClassBinaryPacketTest)
+{
+    MockBufferManager bufferManager(40);
+    TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+    std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket();
+
+    const uint64_t entityBinaryPacketProfilingGuid = 123456u;
+    sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid);
+
+    const uint64_t eventClassBinaryPacketProfilingGuid = 789123u;
+    sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid);
+
+    // Commit the messages
+    sendTimelinePacket->Commit();
+
+    // Get the readable buffer
+    auto packetBuffer = bufferManager.GetReadableBuffer();
+
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    // Check the packet header
+    unsigned int offset = 0;
+
+    // Reading TimelineEntityClassBinaryPacket
+    uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, 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(packetBuffer, offset);
+    uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t entityBinaryPacketDataLength       = (entityBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
+    BOOST_CHECK(entityBinaryPacketDataLength       == 8);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t entitytDecId = ReadUint32(packetBuffer, offset);
+
+    BOOST_CHECK(entitytDecId == uint32_t(1));
+
+    // Check the profiling GUID
+    offset += uint32_t_size;
+    uint64_t readProfilingGuid = ReadUint64(packetBuffer, offset);
+
+    BOOST_CHECK(readProfilingGuid == entityBinaryPacketProfilingGuid);
+
+    // Reading TimelineEventClassBinaryPacket
+    offset += uint64_t_size;
+    uint32_t eventClassBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset);
+    uint32_t eventClassBinaryPacketFamily = (eventClassBinaryPacketHeaderWord0 >> 26) & 0x0000003F;
+    uint32_t eventClassBinaryPacketClass  = (eventClassBinaryPacketHeaderWord0 >> 19) & 0x0000007F;
+    uint32_t eventClassBinaryPacketType   = (eventClassBinaryPacketHeaderWord0 >> 16) & 0x00000007;
+    uint32_t eventClassBinaryPacketStreamId     = (eventClassBinaryPacketHeaderWord0 >>  0) & 0x00000007;
+
+    BOOST_CHECK(eventClassBinaryPacketFamily == 1);
+    BOOST_CHECK(eventClassBinaryPacketClass  == 0);
+    BOOST_CHECK(eventClassBinaryPacketType   == 1);
+    BOOST_CHECK(eventClassBinaryPacketStreamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t eventClassBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset);
+    uint32_t eventClassBinaryPacketSequenceNumbered = (eventClassBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t eventClassBinaryPacketDataLength       = (eventClassBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(eventClassBinaryPacketSequenceNumbered == 0);
+    BOOST_CHECK(eventClassBinaryPacketDataLength       == 12);
+
+    offset += uint32_t_size;
+    uint32_t eventClassDeclId = ReadUint32(packetBuffer, offset);
+    BOOST_CHECK(eventClassDeclId == uint32_t(2));
+
+    // Check the profiling GUID
+    offset += uint32_t_size;
+    readProfilingGuid = ReadUint64(packetBuffer, offset);
+    BOOST_CHECK(readProfilingGuid == eventClassBinaryPacketProfilingGuid);
+
+    bufferManager.MarkRead(packetBuffer);
+}
+
+BOOST_AUTO_TEST_CASE(SendTimelinePacketTests1)
+{
+    unsigned int uint32_t_size = sizeof(uint32_t);
+    unsigned int uint64_t_size = sizeof(uint64_t);
+
+    MockBufferManager bufferManager(512);
+    TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+    std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket();
+
+    // Send TimelineEntityClassBinaryPacket
+    const uint64_t entityBinaryPacketProfilingGuid = 123456u;
+    sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid);
+
+    // Commit the buffer
+    sendTimelinePacket->Commit();
+
+    // Get the readable buffer
+    auto packetBuffer = bufferManager.GetReadableBuffer();
+
+    // Check the packet header
+    unsigned int offset = 0;
+
+    // Reading TimelineEntityClassBinaryPacket
+    uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, 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(packetBuffer, offset);
+    uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t entityBinaryPacketDataLength       = (entityBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
+    BOOST_CHECK(entityBinaryPacketDataLength       == 8);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t entitytDecId = ReadUint32(packetBuffer, offset);
+
+    BOOST_CHECK(entitytDecId == uint32_t(1));
+
+    // Check the profiling GUID
+    offset += uint32_t_size;
+    uint64_t readProfilingGuid = ReadUint64(packetBuffer, offset);
+
+    BOOST_CHECK(readProfilingGuid == entityBinaryPacketProfilingGuid);
+
+    bufferManager.MarkRead(packetBuffer);
+
+    // Send TimelineEventClassBinaryPacket
+    const uint64_t eventClassBinaryPacketProfilingGuid = 789123u;
+    sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid);
+
+    // Commit the buffer
+    sendTimelinePacket->Commit();
+
+    // Get the readable buffer
+    packetBuffer = bufferManager.GetReadableBuffer();
+
+    // Check the packet header
+    offset = 0;
+
+    // Reading TimelineEventClassBinaryPacket
+    uint32_t eventClassBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset);
+    uint32_t eventClassBinaryPacketFamily = (eventClassBinaryPacketHeaderWord0 >> 26) & 0x0000003F;
+    uint32_t eventClassBinaryPacketClass  = (eventClassBinaryPacketHeaderWord0 >> 19) & 0x0000007F;
+    uint32_t eventClassBinaryPacketType   = (eventClassBinaryPacketHeaderWord0 >> 16) & 0x00000007;
+    uint32_t eventClassBinaryPacketStreamId     = (eventClassBinaryPacketHeaderWord0 >>  0) & 0x00000007;
+
+    BOOST_CHECK(eventClassBinaryPacketFamily == 1);
+    BOOST_CHECK(eventClassBinaryPacketClass  == 0);
+    BOOST_CHECK(eventClassBinaryPacketType   == 1);
+    BOOST_CHECK(eventClassBinaryPacketStreamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t eventClassBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset);
+    uint32_t eventClassBinaryPacketSequenceNumbered = (eventClassBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t eventClassBinaryPacketDataLength       = (eventClassBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(eventClassBinaryPacketSequenceNumbered == 0);
+    BOOST_CHECK(eventClassBinaryPacketDataLength       == 12);
+
+    offset += uint32_t_size;
+    uint32_t eventClassDeclId = ReadUint32(packetBuffer, offset);
+    BOOST_CHECK(eventClassDeclId == uint32_t(2));
+
+    // Check the profiling GUID
+    offset += uint32_t_size;
+    readProfilingGuid = ReadUint64(packetBuffer, offset);
+    BOOST_CHECK(readProfilingGuid == eventClassBinaryPacketProfilingGuid);
+
+    bufferManager.MarkRead(packetBuffer);
+
+    // Send TimelineEventBinaryPacket
+    const uint64_t timestamp = 456789u;
+    const uint32_t threadId = 654321u;
+    const uint64_t eventProfilingGuid = 123456u;
+    sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventProfilingGuid);
+
+    // Commit the buffer
+    sendTimelinePacket->Commit();
+
+    // Get the readable buffer
+    packetBuffer = bufferManager.GetReadableBuffer();
+
+    // Check the packet header
+    offset = 0;
+
+    // Reading TimelineEventBinaryPacket
+    uint32_t eventBinaryPacketHeaderWord0 = ReadUint32(packetBuffer, offset);
+    uint32_t eventBinaryPacketFamily = (eventBinaryPacketHeaderWord0 >> 26) & 0x0000003F;
+    uint32_t eventBinaryPacketClass  = (eventBinaryPacketHeaderWord0 >> 19) & 0x0000007F;
+    uint32_t eventBinaryPacketType   = (eventBinaryPacketHeaderWord0 >> 16) & 0x00000007;
+    uint32_t eventBinaryPacketStreamId     = (eventBinaryPacketHeaderWord0 >>  0) & 0x00000007;
+
+    BOOST_CHECK(eventBinaryPacketFamily == 1);
+    BOOST_CHECK(eventBinaryPacketClass  == 0);
+    BOOST_CHECK(eventBinaryPacketType   == 1);
+    BOOST_CHECK(eventBinaryPacketStreamId     == 0);
+
+    offset += uint32_t_size;
+    uint32_t eventBinaryPacketHeaderWord1 = ReadUint32(packetBuffer, offset);
+    uint32_t eventBinaryPacketSequenceNumbered = (eventBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+    uint32_t eventBinaryPacketDataLength       = (eventBinaryPacketHeaderWord1 >>  0) & 0x00FFFFFF;
+    BOOST_CHECK(eventBinaryPacketSequenceNumbered == 0);
+    BOOST_CHECK(eventBinaryPacketDataLength       == 24);
+
+    // Check the decl_id
+    offset += uint32_t_size;
+    uint32_t eventDeclId = ReadUint32(packetBuffer, offset);
+    BOOST_CHECK(eventDeclId == 4);
+
+    // Check the timestamp
+    offset += uint32_t_size;
+    uint64_t eventTimestamp = ReadUint64(packetBuffer, offset);
+    BOOST_CHECK(eventTimestamp == timestamp);
+
+    // Check the thread id
+    offset += uint64_t_size;
+    uint32_t readThreadId = ReadUint32(packetBuffer, offset);
+    BOOST_CHECK(readThreadId == threadId);
+
+    // Check the profiling GUID
+    offset += uint32_t_size;
+    readProfilingGuid = ReadUint64(packetBuffer, offset);
+    BOOST_CHECK(readProfilingGuid == eventProfilingGuid);
+}
+
+BOOST_AUTO_TEST_CASE(SendTimelinePacketTests2)
+{
+    MockBufferManager bufferManager(40);
+    TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+    std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket();
+
+    BOOST_CHECK_THROW(sendTimelinePacket->SendTimelineMessageDirectoryPackage(),
+                      armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendTimelinePacketTests3)
+{
+    MockBufferManager bufferManager(512);
+    TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
+    std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = timelinePacketWriterFactory.GetSendTimelinePacket();
+
+    // Send TimelineEntityClassBinaryPacket
+    const uint64_t entityBinaryPacketProfilingGuid = 123456u;
+    sendTimelinePacket->SendTimelineEntityBinaryPacket(entityBinaryPacketProfilingGuid);
+
+    // Commit the buffer
+    sendTimelinePacket->Commit();
+
+    // Get the readable buffer
+    auto packetBuffer = bufferManager.GetReadableBuffer();
+
+    // Send TimelineEventClassBinaryPacket
+    const uint64_t eventClassBinaryPacketProfilingGuid = 789123u;
+    BOOST_CHECK_THROW(sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassBinaryPacketProfilingGuid),
+                      armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_SUITE_END()