//
-// Copyright © 2017 Arm Ltd. All rights reserved.
+// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
-#include "../IBufferWrapper.hpp"
-#include "../ISendCounterPacket.hpp"
+#include "ProfilingMocks.hpp"
+#include "ProfilingTestUtils.hpp"
+#include "SendCounterPacketTests.hpp"
+
+#include <BufferManager.hpp>
+#include <CounterDirectory.hpp>
+#include <EncodeVersion.hpp>
+#include <ProfilingUtils.hpp>
+#include <SendCounterPacket.hpp>
+#include <Processes.hpp>
+
+#include <armnn/Exceptions.hpp>
+#include <armnn/Conversion.hpp>
+#include <armnn/Utils.hpp>
+
+#include <common/include/Constants.hpp>
+
-#include <iostream>
#include <boost/test/unit_test.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <chrono>
+
+using namespace armnn::profiling;
+
+namespace
+{
+
+// A short delay to wait for the thread to process a packet.
+uint16_t constexpr WAIT_UNTIL_READABLE_MS = 20;
+void SetNotConnectedProfilingState(ProfilingStateMachine& profilingStateMachine)
+{
+ ProfilingState currentState = profilingStateMachine.GetCurrentState();
+ switch (currentState)
+ {
+ case ProfilingState::WaitingForAck:
+ profilingStateMachine.TransitionToState(ProfilingState::Active);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::Uninitialised:
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::Active:
+ profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::NotConnected:
+ return;
+ default:
+ BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
+ }
+}
+
+void SetWaitingForAckProfilingState(ProfilingStateMachine& profilingStateMachine)
+{
+ ProfilingState currentState = profilingStateMachine.GetCurrentState();
+ switch (currentState)
+ {
+ case ProfilingState::Uninitialised:
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::Active:
+ profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::NotConnected:
+ profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::WaitingForAck:
+ return;
+ default:
+ BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
+ }
+}
+
+void SetActiveProfilingState(ProfilingStateMachine& profilingStateMachine)
+{
+ ProfilingState currentState = profilingStateMachine.GetCurrentState();
+ switch (currentState)
+ {
+ case ProfilingState::Uninitialised:
+ profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::NotConnected:
+ profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::WaitingForAck:
+ profilingStateMachine.TransitionToState(ProfilingState::Active);
+ ARMNN_FALLTHROUGH;
+ case ProfilingState::Active:
+ return;
+ default:
+ BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
+ }
+}
+
+} // Anonymous namespace
BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
-using namespace armnn::profiling;
+using PacketType = MockProfilingConnection::PacketType;
+
+BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
+{
+ MockBufferManager mockBuffer(512);
+ MockSendCounterPacket mockSendCounterPacket(mockBuffer);
+
+ mockSendCounterPacket.SendStreamMetaDataPacket();
+
+ auto packetBuffer = mockBuffer.GetReadableBuffer();
+ const char* buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
+
+ BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
+
+ mockBuffer.MarkRead(packetBuffer);
+
+ CounterDirectory counterDirectory;
+ mockSendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
+
+ packetBuffer = mockBuffer.GetReadableBuffer();
+ buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
+
+ BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
+
+ mockBuffer.MarkRead(packetBuffer);
+
+ uint64_t timestamp = 0;
+ std::vector<CounterValue> indexValuePairs;
+
+ mockSendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
+
+ packetBuffer = mockBuffer.GetReadableBuffer();
+ buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
+
+ BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
+
+ mockBuffer.MarkRead(packetBuffer);
+
+ uint32_t capturePeriod = 0;
+ std::vector<uint16_t> selectedCounterIds;
+ mockSendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
+
+ packetBuffer = mockBuffer.GetReadableBuffer();
+ buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
+
+ BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
+
+ mockBuffer.MarkRead(packetBuffer);
+}
+
+BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest)
+{
+ // Error no space left in buffer
+ MockBufferManager mockBuffer1(10);
+ SendCounterPacket sendPacket1(mockBuffer1);
+
+ uint32_t capturePeriod = 1000;
+ std::vector<uint16_t> selectedCounterIds;
+ BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
+ BufferExhaustion);
+
+ // Packet without any counters
+ MockBufferManager mockBuffer2(512);
+ SendCounterPacket sendPacket2(mockBuffer2);
+
+ sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
+ auto readBuffer2 = mockBuffer2.GetReadableBuffer();
+
+ uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
+ uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
+ uint32_t period = ReadUint32(readBuffer2, 8);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
+ BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
+ BOOST_TEST(headerWord1 == 4); // data lenght
+ BOOST_TEST(period == 1000); // capture period
-class MockBuffer : public IBufferWrapper
+ // Full packet message
+ MockBufferManager mockBuffer3(512);
+ SendCounterPacket sendPacket3(mockBuffer3);
+
+ selectedCounterIds.reserve(5);
+ selectedCounterIds.emplace_back(100);
+ selectedCounterIds.emplace_back(200);
+ selectedCounterIds.emplace_back(300);
+ selectedCounterIds.emplace_back(400);
+ selectedCounterIds.emplace_back(500);
+ sendPacket3.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
+ auto readBuffer3 = mockBuffer3.GetReadableBuffer();
+
+ headerWord0 = ReadUint32(readBuffer3, 0);
+ headerWord1 = ReadUint32(readBuffer3, 4);
+ period = ReadUint32(readBuffer3, 8);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
+ BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
+ BOOST_TEST(headerWord1 == 14); // data lenght
+ BOOST_TEST(period == 1000); // capture period
+
+ uint16_t counterId = 0;
+ uint32_t offset = 12;
+
+ // Counter Ids
+ for(const uint16_t& id : selectedCounterIds)
+ {
+ counterId = ReadUint16(readBuffer3, offset);
+ BOOST_TEST(counterId == id);
+ offset += 2;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest)
{
-public:
- MockBuffer() : m_Buffer() {}
+ ProfilingStateMachine profilingStateMachine;
+
+ // Error no space left in buffer
+ MockBufferManager mockBuffer1(10);
+ SendCounterPacket sendPacket1(mockBuffer1);
+
+ auto captureTimestamp = std::chrono::steady_clock::now();
+ uint64_t time = static_cast<uint64_t >(captureTimestamp.time_since_epoch().count());
+ std::vector<CounterValue> indexValuePairs;
+
+ BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterCapturePacket(time, indexValuePairs),
+ BufferExhaustion);
+
+ // Packet without any counters
+ MockBufferManager mockBuffer2(512);
+ SendCounterPacket sendPacket2(mockBuffer2);
+
+ sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs);
+ auto readBuffer2 = mockBuffer2.GetReadableBuffer();
+
+ uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
+ uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
+ uint64_t readTimestamp = ReadUint64(readBuffer2, 8);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
+ BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
+ BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
+ BOOST_TEST(headerWord1 == 8); // data length
+ BOOST_TEST(time == readTimestamp); // capture period
- unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
+ // Full packet message
+ MockBufferManager mockBuffer3(512);
+ SendCounterPacket sendPacket3(mockBuffer3);
+
+ indexValuePairs.reserve(5);
+ indexValuePairs.emplace_back(CounterValue{0, 100});
+ indexValuePairs.emplace_back(CounterValue{1, 200});
+ indexValuePairs.emplace_back(CounterValue{2, 300});
+ indexValuePairs.emplace_back(CounterValue{3, 400});
+ indexValuePairs.emplace_back(CounterValue{4, 500});
+ sendPacket3.SendPeriodicCounterCapturePacket(time, indexValuePairs);
+ auto readBuffer3 = mockBuffer3.GetReadableBuffer();
+
+ headerWord0 = ReadUint32(readBuffer3, 0);
+ headerWord1 = ReadUint32(readBuffer3, 4);
+ uint64_t readTimestamp2 = ReadUint64(readBuffer3, 8);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
+ BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
+ BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
+ BOOST_TEST(headerWord1 == 38); // data length
+ BOOST_TEST(time == readTimestamp2); // capture period
+
+ uint16_t counterIndex = 0;
+ uint32_t counterValue = 100;
+ uint32_t offset = 16;
+
+ // Counter Ids
+ for (auto it = indexValuePairs.begin(), end = indexValuePairs.end(); it != end; ++it)
{
- if (requestedSize > m_BufferSize)
- {
- reservedSize = m_BufferSize;
- }
- else
+ // Check Counter Index
+ uint16_t readIndex = ReadUint16(readBuffer3, offset);
+ BOOST_TEST(counterIndex == readIndex);
+ counterIndex++;
+ offset += 2;
+
+ // Check Counter Value
+ uint32_t readValue = ReadUint32(readBuffer3, offset);
+ BOOST_TEST(counterValue == readValue);
+ counterValue += 100;
+ offset += 4;
+ }
+
+}
+
+BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
+{
+ using boost::numeric_cast;
+
+ uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
+
+ // Error no space left in buffer
+ MockBufferManager mockBuffer1(10);
+ SendCounterPacket sendPacket1(mockBuffer1);
+ BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion);
+
+ // Full metadata packet
+
+ std::string processName = GetProcessName().substr(0, 60);
+
+ uint32_t infoSize = numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1;
+ uint32_t hardwareVersionSize = numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1;
+ uint32_t softwareVersionSize = numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1;
+ uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) + 1;
+
+ uint32_t packetEntries = 6;
+
+ MockBufferManager mockBuffer2(512);
+ SendCounterPacket sendPacket2(mockBuffer2);
+ sendPacket2.SendStreamMetaDataPacket();
+ auto readBuffer2 = mockBuffer2.GetReadableBuffer();
+
+ uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
+ uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
+ BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id
+
+ uint32_t totalLength = numeric_cast<uint32_t>(2 * sizeUint32 + 10 * sizeUint32 + infoSize + hardwareVersionSize +
+ softwareVersionSize + processNameSize + sizeUint32 +
+ 2 * packetEntries * sizeUint32);
+
+ BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length
+
+ uint32_t offset = sizeUint32 * 2;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == armnnProfiling::PIPE_MAGIC); // pipe_magic
+ offset += sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version
+ offset += sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == MAX_METADATA_PACKET_LENGTH); // max_data_len
+ offset += sizeUint32;
+ int pid = armnnUtils::Processes::GetCurrentId();
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast<uint32_t>(pid));
+ offset += sizeUint32;
+ uint32_t poolOffset = 10 * sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_info
+ offset += sizeUint32;
+ poolOffset += infoSize;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_hw_version
+ offset += sizeUint32;
+ poolOffset += hardwareVersionSize;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_sw_version
+ offset += sizeUint32;
+ poolOffset += softwareVersionSize;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_process_name
+ offset += sizeUint32;
+ poolOffset += processNameSize;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_packet_version_table
+ offset += sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved
+
+ const unsigned char* readData2 = readBuffer2->GetReadableData();
+
+ offset += sizeUint32;
+ if (infoSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareInfo().c_str()) == 0);
+ offset += infoSize;
+ }
+
+ if (hardwareVersionSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetHardwareVersion().c_str()) == 0);
+ offset += hardwareVersionSize;
+ }
+
+ if (softwareVersionSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareVersion().c_str()) == 0);
+ offset += softwareVersionSize;
+ }
+
+ if (processNameSize)
+ {
+ BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetProcessName().c_str()) == 0);
+ offset += processNameSize;
+ }
+
+ if (packetEntries)
+ {
+ BOOST_TEST((ReadUint32(readBuffer2, offset) >> 16) == packetEntries);
+ offset += sizeUint32;
+ for (uint32_t i = 0; i < packetEntries - 1; ++i)
{
- reservedSize = requestedSize;
+ BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 0);
+ BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == i);
+ offset += sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
+ offset += sizeUint32;
}
- return m_Buffer;
+ BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 1);
+ BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == 0);
+ offset += sizeUint32;
+ BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
+ offset += sizeUint32;
}
- void Commit(unsigned int size) override {}
+ BOOST_TEST(offset == totalLength);
+}
+
+BOOST_AUTO_TEST_CASE(CreateDeviceRecordTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a device for testing
+ uint16_t deviceUid = 27;
+ const std::string deviceName = "some_device";
+ uint16_t deviceCores = 3;
+ const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
+
+ // Create a device record
+ SendCounterPacket::DeviceRecord deviceRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
+
+ BOOST_CHECK(result);
+ BOOST_CHECK(errorMessage.empty());
+ BOOST_CHECK(deviceRecord.size() == 6); // Size in words: header [2] + device name [4]
- const unsigned char* GetReadBuffer(unsigned int& size) override
+ uint16_t deviceRecordWord0[]
{
- size = static_cast<unsigned int>(strlen(reinterpret_cast<const char*>(m_Buffer)) + 1);
- return m_Buffer;
- }
+ static_cast<uint16_t>(deviceRecord[0] >> 16),
+ static_cast<uint16_t>(deviceRecord[0])
+ };
+ BOOST_CHECK(deviceRecordWord0[0] == deviceUid); // uid
+ BOOST_CHECK(deviceRecordWord0[1] == deviceCores); // cores
+ BOOST_CHECK(deviceRecord[1] == 8); // name_offset
+ BOOST_CHECK(deviceRecord[2] == deviceName.size() + 1); // The length of the SWTrace string (name)
+ BOOST_CHECK(std::memcmp(deviceRecord.data() + 3, deviceName.data(), deviceName.size()) == 0); // name
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidDeviceRecordTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a device for testing
+ uint16_t deviceUid = 27;
+ const std::string deviceName = "some€£invalid‡device";
+ uint16_t deviceCores = 3;
+ const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
+
+ // Create a device record
+ SendCounterPacket::DeviceRecord deviceRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(deviceRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(CreateCounterSetRecordTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter set for testing
+ uint16_t counterSetUid = 27;
+ const std::string counterSetName = "some_counter_set";
+ uint16_t counterSetCount = 3421;
+ const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
+
+ // Create a counter set record
+ SendCounterPacket::CounterSetRecord counterSetRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
+
+ BOOST_CHECK(result);
+ BOOST_CHECK(errorMessage.empty());
+ BOOST_CHECK(counterSetRecord.size() == 8); // Size in words: header [2] + counter set name [6]
+
+ uint16_t counterSetRecordWord0[]
+ {
+ static_cast<uint16_t>(counterSetRecord[0] >> 16),
+ static_cast<uint16_t>(counterSetRecord[0])
+ };
+ BOOST_CHECK(counterSetRecordWord0[0] == counterSetUid); // uid
+ BOOST_CHECK(counterSetRecordWord0[1] == counterSetCount); // cores
+ BOOST_CHECK(counterSetRecord[1] == 8); // name_offset
+ BOOST_CHECK(counterSetRecord[2] == counterSetName.size() + 1); // The length of the SWTrace string (name)
+ BOOST_CHECK(std::memcmp(counterSetRecord.data() + 3, counterSetName.data(), counterSetName.size()) == 0); // name
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidCounterSetRecordTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter set for testing
+ uint16_t counterSetUid = 27;
+ const std::string counterSetName = "some invalid_counter€£set";
+ uint16_t counterSetCount = 3421;
+ const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
+
+ // Create a counter set record
+ SendCounterPacket::CounterSetRecord counterSetRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(counterSetRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(CreateEventRecordTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter for testing
+ uint16_t counterUid = 7256;
+ uint16_t maxCounterUid = 132;
+ uint16_t deviceUid = 132;
+ uint16_t counterSetUid = 4497;
+ uint16_t counterClass = 1;
+ uint16_t counterInterpolation = 1;
+ double counterMultiplier = 1234.567f;
+ const std::string counterName = "some_valid_counter";
+ const std::string counterDescription = "a_counter_for_testing";
+ const std::string counterUnits = "Mrads2";
+ const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
+ counterUid,
+ maxCounterUid,
+ counterClass,
+ counterInterpolation,
+ counterMultiplier,
+ counterName,
+ counterDescription,
+ counterUnits,
+ deviceUid,
+ counterSetUid);
+ ARMNN_ASSERT(counter);
+
+ // Create an event record
+ SendCounterPacket::EventRecord eventRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
+
+ BOOST_CHECK(result);
+ BOOST_CHECK(errorMessage.empty());
+ BOOST_CHECK(eventRecord.size() == 24); // Size in words: header [8] + counter name [6] + description [7] + units [3]
+
+ uint16_t eventRecordWord0[]
+ {
+ static_cast<uint16_t>(eventRecord[0] >> 16),
+ static_cast<uint16_t>(eventRecord[0])
+ };
+ uint16_t eventRecordWord1[]
+ {
+ static_cast<uint16_t>(eventRecord[1] >> 16),
+ static_cast<uint16_t>(eventRecord[1])
+ };
+ uint16_t eventRecordWord2[]
+ {
+ static_cast<uint16_t>(eventRecord[2] >> 16),
+ static_cast<uint16_t>(eventRecord[2])
+ };
+ uint32_t eventRecordWord34[]
+ {
+ eventRecord[3],
+ eventRecord[4]
+ };
+
+ BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
+ BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
+ BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
+
+ BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
+ BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
+ BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
+ BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
+
+ ARMNN_NO_CONVERSION_WARN_BEGIN
+ uint32_t eventRecordBlockSize = 8u * sizeof(uint32_t);
+ uint32_t counterNameOffset = eventRecordBlockSize; // The name is the first item in pool
+ uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
+ 4u + // Counter name length (uint32_t)
+ counterName.size() + // 18u
+ 1u + // Null-terminator
+ 1u; // Rounding to the next word
+
+ size_t counterUnitsOffset = counterDescriptionOffset + // Counter description offset
+ 4u + // Counter description length (uint32_t)
+ counterDescription.size() + // 21u
+ 1u + // Null-terminator
+ 2u; // Rounding to the next word
+
+ ARMNN_NO_CONVERSION_WARN_END
+
+ BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
+ BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
+ BOOST_CHECK(eventRecord[7] == counterUnitsOffset); // units_offset
+
+ // Offsets are relative to the start of the eventRecord
+ auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data());
+ size_t uint32_t_size = sizeof(uint32_t);
+
+ // The length of the SWTrace string (name)
+ BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
+ // The counter name
+ BOOST_CHECK(std::memcmp(eventRecordPool +
+ counterNameOffset + // Offset
+ uint32_t_size /* The length of the name */,
+ counterName.data(),
+ counterName.size()) == 0); // name
+ // The null-terminator at the end of the name
+ BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
+
+ // The length of the SWTrace string (description)
+ BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
+ // The counter description
+ BOOST_CHECK(std::memcmp(eventRecordPool +
+ counterDescriptionOffset + // Offset
+ uint32_t_size /* The length of the description */,
+ counterDescription.data(),
+ counterDescription.size()) == 0); // description
+ // The null-terminator at the end of the description
+ BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
+
+ // The length of the SWTrace namestring (units)
+ BOOST_CHECK(eventRecordPool[counterUnitsOffset] == counterUnits.size() + 1);
+ // The counter units
+ BOOST_CHECK(std::memcmp(eventRecordPool +
+ counterUnitsOffset + // Offset
+ uint32_t_size /* The length of the units */,
+ counterUnits.data(),
+ counterUnits.size()) == 0); // units
+ // The null-terminator at the end of the units
+ BOOST_CHECK(eventRecordPool[counterUnitsOffset + uint32_t_size + counterUnits.size()] == '\0');
+}
+
+BOOST_AUTO_TEST_CASE(CreateEventRecordNoUnitsTest)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter for testing
+ uint16_t counterUid = 44312;
+ uint16_t maxCounterUid = 345;
+ uint16_t deviceUid = 101;
+ uint16_t counterSetUid = 34035;
+ uint16_t counterClass = 0;
+ uint16_t counterInterpolation = 1;
+ double counterMultiplier = 4435.0023f;
+ const std::string counterName = "some_valid_counter";
+ const std::string counterDescription = "a_counter_for_testing";
+ const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
+ counterUid,
+ maxCounterUid,
+ counterClass,
+ counterInterpolation,
+ counterMultiplier,
+ counterName,
+ counterDescription,
+ "",
+ deviceUid,
+ counterSetUid);
+ ARMNN_ASSERT(counter);
+
+ // Create an event record
+ SendCounterPacket::EventRecord eventRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
+
+ BOOST_CHECK(result);
+ BOOST_CHECK(errorMessage.empty());
+ BOOST_CHECK(eventRecord.size() == 21); // Size in words: header [8] + counter name [6] + description [7]
+
+ uint16_t eventRecordWord0[]
+ {
+ static_cast<uint16_t>(eventRecord[0] >> 16),
+ static_cast<uint16_t>(eventRecord[0])
+ };
+ uint16_t eventRecordWord1[]
+ {
+ static_cast<uint16_t>(eventRecord[1] >> 16),
+ static_cast<uint16_t>(eventRecord[1])
+ };
+ uint16_t eventRecordWord2[]
+ {
+ static_cast<uint16_t>(eventRecord[2] >> 16),
+ static_cast<uint16_t>(eventRecord[2])
+ };
+ uint32_t eventRecordWord34[]
+ {
+ eventRecord[3],
+ eventRecord[4]
+ };
+ BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
+ BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
+ BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
+ BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
+ BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
+ BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
+ BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
+
+ ARMNN_NO_CONVERSION_WARN_BEGIN
+ uint32_t eventRecordBlockSize = 8u * sizeof(uint32_t);
+ uint32_t counterNameOffset = eventRecordBlockSize; // The name is the first item in pool
+ uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
+ 4u + // Counter name length (uint32_t)
+ counterName.size() + // 18u
+ 1u + // Null-terminator
+ 1u; // Rounding to the next word
+ ARMNN_NO_CONVERSION_WARN_END
+
+ BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
+ BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
+ BOOST_CHECK(eventRecord[7] == 0); // units_offset
+
+ // Offsets are relative to the start of the eventRecord
+ auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data());
+ size_t uint32_t_size = sizeof(uint32_t);
+
+ // The length of the SWTrace string (name)
+ BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
+ // The counter name
+ BOOST_CHECK(std::memcmp(eventRecordPool +
+ counterNameOffset + // Offset
+ uint32_t_size, // The length of the name
+ counterName.data(),
+ counterName.size()) == 0); // name
+ // The null-terminator at the end of the name
+ BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
+
+ // The length of the SWTrace string (description)
+ BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
+ // The counter description
+ BOOST_CHECK(std::memcmp(eventRecordPool +
+ counterDescriptionOffset + // Offset
+ uint32_t_size, // The length of the description
+ counterDescription.data(),
+ counterDescription.size()) == 0); // description
+ // The null-terminator at the end of the description
+ BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest1)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter for testing
+ uint16_t counterUid = 7256;
+ uint16_t maxCounterUid = 132;
+ uint16_t deviceUid = 132;
+ uint16_t counterSetUid = 4497;
+ uint16_t counterClass = 1;
+ uint16_t counterInterpolation = 1;
+ double counterMultiplier = 1234.567f;
+ const std::string counterName = "some_invalid_counter £££"; // Invalid name
+ const std::string counterDescription = "a_counter_for_testing";
+ const std::string counterUnits = "Mrads2";
+ const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
+ counterUid,
+ maxCounterUid,
+ counterClass,
+ counterInterpolation,
+ counterMultiplier,
+ counterName,
+ counterDescription,
+ counterUnits,
+ deviceUid,
+ counterSetUid);
+ ARMNN_ASSERT(counter);
- void Release( unsigned int size) override {}
+ // Create an event record
+ SendCounterPacket::EventRecord eventRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
-private:
- static const unsigned int m_BufferSize = 512;
- unsigned char m_Buffer[m_BufferSize];
-};
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(eventRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest2)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter for testing
+ uint16_t counterUid = 7256;
+ uint16_t maxCounterUid = 132;
+ uint16_t deviceUid = 132;
+ uint16_t counterSetUid = 4497;
+ uint16_t counterClass = 1;
+ uint16_t counterInterpolation = 1;
+ double counterMultiplier = 1234.567f;
+ const std::string counterName = "some_invalid_counter";
+ const std::string counterDescription = "an invalid d€scription"; // Invalid description
+ const std::string counterUnits = "Mrads2";
+ const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
+ counterUid,
+ maxCounterUid,
+ counterClass,
+ counterInterpolation,
+ counterMultiplier,
+ counterName,
+ counterDescription,
+ counterUnits,
+ deviceUid,
+ counterSetUid);
+ ARMNN_ASSERT(counter);
+
+ // Create an event record
+ SendCounterPacket::EventRecord eventRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(eventRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest3)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a counter for testing
+ uint16_t counterUid = 7256;
+ uint16_t maxCounterUid = 132;
+ uint16_t deviceUid = 132;
+ uint16_t counterSetUid = 4497;
+ uint16_t counterClass = 1;
+ uint16_t counterInterpolation = 1;
+ double counterMultiplier = 1234.567f;
+ const std::string counterName = "some_invalid_counter";
+ const std::string counterDescription = "a valid description";
+ const std::string counterUnits = "Mrad s2"; // Invalid units
+ const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
+ counterUid,
+ maxCounterUid,
+ counterClass,
+ counterInterpolation,
+ counterMultiplier,
+ counterName,
+ counterDescription,
+ counterUnits,
+ deviceUid,
+ counterSetUid);
+ ARMNN_ASSERT(counter);
+
+ // Create an event record
+ SendCounterPacket::EventRecord eventRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(eventRecord.empty());
+}
-class MockSendCounterPacket : public ISendCounterPacket
+BOOST_AUTO_TEST_CASE(CreateCategoryRecordTest)
{
-public:
- MockSendCounterPacket(IBufferWrapper& sendBuffer) : m_Buffer(sendBuffer) {}
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a category for testing
+ const std::string categoryName = "some_category";
+ const CategoryPtr category = std::make_unique<Category>(categoryName);
+ ARMNN_ASSERT(category);
+ category->m_Counters = { 11u, 23u, 5670u };
+
+ // Create a collection of counters
+ Counters counters;
+ counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
+ CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
+ 0,
+ 11,
+ 0,
+ 0,
+ 534.0003f,
+ "counter1",
+ "the first counter",
+ "millipi2",
+ 0,
+ 0))));
+ counters.insert(std::make_pair<uint16_t, CounterPtr>(23,
+ CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
+ 1,
+ 23,
+ 0,
+ 1,
+ 534.0003f,
+ "this is counter 2",
+ "the second counter",
+ "",
+ 0,
+ 0))));
+ counters.insert(std::make_pair<uint16_t, CounterPtr>(5670,
+ CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
+ 2,
+ 5670,
+ 0,
+ 0,
+ 534.0003f,
+ "and this is number 3",
+ "the third counter",
+ "blah_per_second",
+ 0,
+ 0))));
+ Counter* counter1 = counters.find(11)->second.get();
+ Counter* counter2 = counters.find(23)->second.get();
+ Counter* counter3 = counters.find(5670)->second.get();
+ ARMNN_ASSERT(counter1);
+ ARMNN_ASSERT(counter2);
+ ARMNN_ASSERT(counter3);
+ uint16_t categoryEventCount = boost::numeric_cast<uint16_t>(counters.size());
+
+ // Create a category record
+ SendCounterPacket::CategoryRecord categoryRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
- void SendStreamMetaDataPacket() override
+ BOOST_CHECK(result);
+ BOOST_CHECK(errorMessage.empty());
+ BOOST_CHECK(categoryRecord.size() == 79); // Size in words: header [3] + event pointer table [3] +
+ // category name [5] + event records [68 = 22 + 20 + 26]
+
+ uint16_t categoryRecordWord1[]
{
- std::string message("SendStreamMetaDataPacket");
- unsigned int reserved = 0;
- unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
- memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
+ static_cast<uint16_t>(categoryRecord[0] >> 16),
+ static_cast<uint16_t>(categoryRecord[0])
+ };
+ BOOST_CHECK(categoryRecordWord1[0] == categoryEventCount); // event_count
+ BOOST_CHECK(categoryRecordWord1[1] == 0); // reserved
+
+ size_t uint32_t_size = sizeof(uint32_t);
+
+ ARMNN_NO_CONVERSION_WARN_BEGIN
+ uint32_t categoryRecordBlockSize = 3u * uint32_t_size;
+ uint32_t eventPointerTableOffset = categoryRecordBlockSize; // The event pointer table is the first item in pool
+ uint32_t categoryNameOffset = eventPointerTableOffset + // Event pointer table offset
+ categoryEventCount * uint32_t_size; // The size of the event pointer table
+ ARMNN_NO_CONVERSION_WARN_END
+
+ BOOST_CHECK(categoryRecord[1] == eventPointerTableOffset); // event_pointer_table_offset
+ BOOST_CHECK(categoryRecord[2] == categoryNameOffset); // name_offset
+ // Offsets are relative to the start of the category record
+ auto categoryRecordPool = reinterpret_cast<unsigned char*>(categoryRecord.data());
+
+ // The event pointer table
+ uint32_t eventRecord0Offset = categoryRecordPool[eventPointerTableOffset + 0 * uint32_t_size];
+ uint32_t eventRecord1Offset = categoryRecordPool[eventPointerTableOffset + 1 * uint32_t_size];
+ uint32_t eventRecord2Offset = categoryRecordPool[eventPointerTableOffset + 2 * uint32_t_size];
+ BOOST_CHECK(eventRecord0Offset == 32);
+ BOOST_CHECK(eventRecord1Offset == 120);
+ BOOST_CHECK(eventRecord2Offset == 200);
+
+ // The length of the SWTrace namestring (name)
+ BOOST_CHECK(categoryRecordPool[categoryNameOffset] == categoryName.size() + 1);
+ // The category name
+ BOOST_CHECK(std::memcmp(categoryRecordPool +
+ categoryNameOffset + // Offset
+ uint32_t_size, // The length of the name
+ categoryName.data(),
+ categoryName.size()) == 0); // name
+ // The null-terminator at the end of the name
+ BOOST_CHECK(categoryRecordPool[categoryNameOffset + uint32_t_size + categoryName.size()] == '\0');
+
+ // For brevity, checking only the UIDs, max counter UIDs and names of the counters in the event records,
+ // as the event records already have a number of unit tests dedicated to them
+
+ // Counter1 UID and max counter UID
+ uint16_t eventRecord0Word0[2] = { 0u, 0u };
+ std::memcpy(eventRecord0Word0, categoryRecordPool + categoryRecordBlockSize + eventRecord0Offset,
+ sizeof(eventRecord0Word0));
+ BOOST_CHECK(eventRecord0Word0[0] == counter1->m_Uid);
+ BOOST_CHECK(eventRecord0Word0[1] == counter1->m_MaxCounterUid);
+
+ // Counter1 name
+ uint32_t counter1NameOffset = 0;
+ std::memcpy(&counter1NameOffset, categoryRecordPool + eventRecord0Offset + 5u * uint32_t_size, uint32_t_size);
+ BOOST_CHECK(counter1NameOffset == 0);
+ // The length of the SWTrace string (name)
+ BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
+ categoryRecordBlockSize + // Offset to the end of the category record block
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter1NameOffset // Offset to the name of the counter
+ ] == counter1->m_Name.size() + 1); // The length of the name including the
+ // null-terminator
+ // The counter1 name
+ BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
+ categoryRecordBlockSize + // Offset to the end of the category record block
+ eventRecord0Offset + // Offset to the event record
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter1NameOffset + // Offset to the name of the counter
+ uint32_t_size, // The length of the name
+ counter1->m_Name.data(),
+ counter1->m_Name.size()) == 0); // name
+ // The null-terminator at the end of the counter1 name
+ BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
+ categoryRecordBlockSize + // Offset to the end of the category record block
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter1NameOffset + // Offset to the name of the counter
+ uint32_t_size + // The length of the name
+ counter1->m_Name.size() // The name of the counter
+ ] == '\0');
+
+ // Counter2 name
+ uint32_t counter2NameOffset = 0;
+ std::memcpy(&counter2NameOffset, categoryRecordPool +
+ categoryRecordBlockSize +
+ eventRecord1Offset +
+ 5u * uint32_t_size,
+ uint32_t_size);
+ BOOST_CHECK(counter2NameOffset == 8u * uint32_t_size );
+ // The length of the SWTrace string (name)
+
+ BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
+ categoryRecordBlockSize +
+ counter2NameOffset // Offset to the name of the counter
+ ] == counter2->m_Name.size() + 1); // The length of the name including the
+ // null-terminator
+ // The counter2 name
+ BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
+ categoryRecordBlockSize + // Offset to the end of the category record block
+ eventRecord1Offset + // Offset to the event record
+ counter2NameOffset + // Offset to the name of the counter
+ uint32_t_size, // The length of the name
+ counter2->m_Name.data(),
+ counter2->m_Name.size()) == 0); // name
+
+
+ // The null-terminator at the end of the counter2 name
+ BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
+ categoryRecordBlockSize + // Offset to the end of the category record block
+ counter2NameOffset + // Offset to the name of the counter
+ uint32_t_size + // The length of the name
+ counter2->m_Name.size() // The name of the counter
+ ] == '\0');
+
+ // Counter3 name
+ uint32_t counter3NameOffset = 0;
+ std::memcpy(&counter3NameOffset, categoryRecordPool + eventRecord2Offset + 5u * uint32_t_size, uint32_t_size);
+ BOOST_CHECK(counter3NameOffset == 0);
+ // The length of the SWTrace string (name)
+ BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
+ categoryRecordBlockSize +
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter3NameOffset // Offset to the name of the counter
+ ] == counter3->m_Name.size() + 1); // The length of the name including the
+ // null-terminator
+ // The counter3 name
+ BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
+ categoryRecordBlockSize +
+ eventRecord2Offset + // Offset to the event record
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter3NameOffset + // Offset to the name of the counter
+ uint32_t_size, // The length of the name
+ counter3->m_Name.data(),
+ counter3->m_Name.size()) == 0); // name
+ // The null-terminator at the end of the counter3 name
+ BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
+ categoryRecordBlockSize +
+ 8u * uint32_t_size + // Offset to the event record pool
+ counter3NameOffset + // Offset to the name of the counter
+ uint32_t_size + // The length of the name
+ counter3->m_Name.size() // The name of the counter
+ ] == '\0');
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest1)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a category for testing
+ const std::string categoryName = "some invalid category";
+ const CategoryPtr category = std::make_unique<Category>(categoryName);
+ BOOST_CHECK(category);
+
+ // Create a category record
+ Counters counters;
+ SendCounterPacket::CategoryRecord categoryRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(categoryRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest2)
+{
+ MockBufferManager mockBuffer(0);
+ SendCounterPacketTest sendCounterPacketTest(mockBuffer);
+
+ // Create a category for testing
+ const std::string categoryName = "some_category";
+ const CategoryPtr category = std::make_unique<Category>(categoryName);
+ BOOST_CHECK(category);
+ category->m_Counters = { 11u, 23u, 5670u };
+
+ // Create a collection of counters
+ Counters counters;
+ counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
+ CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
+ 11,
+ 1234,
+ 0,
+ 1,
+ 534.0003f,
+ "count€r1", // Invalid name
+ "the first counter",
+ "millipi2",
+ 0,
+ 0))));
+
+ Counter* counter1 = counters.find(11)->second.get();
+ BOOST_CHECK(counter1);
+
+ // Create a category record
+ SendCounterPacket::CategoryRecord categoryRecord;
+ std::string errorMessage;
+ bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
+
+ BOOST_CHECK(!result);
+ BOOST_CHECK(!errorMessage.empty());
+ BOOST_CHECK(categoryRecord.empty());
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest1)
+{
+ // The counter directory used for testing
+ CounterDirectory counterDirectory;
+
+ // Register a device
+ const std::string device1Name = "device1";
+ const Device* device1 = nullptr;
+ BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
+ BOOST_CHECK(device1);
+
+ // Register a device
+ const std::string device2Name = "device2";
+ const Device* device2 = nullptr;
+ BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
+ BOOST_CHECK(device2);
+
+ // Buffer with not enough space
+ MockBufferManager mockBuffer(10);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory),
+ armnn::profiling::BufferExhaustion);
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest2)
+{
+ // The counter directory used for testing
+ CounterDirectory counterDirectory;
+
+ // Register a device
+ const std::string device1Name = "device1";
+ const Device* device1 = nullptr;
+ BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
+ BOOST_CHECK(device1);
+
+ // Register a device
+ const std::string device2Name = "device2";
+ const Device* device2 = nullptr;
+ BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
+ BOOST_CHECK(device2);
+
+ // Register a counter set
+ const std::string counterSet1Name = "counterset1";
+ const CounterSet* counterSet1 = nullptr;
+ BOOST_CHECK_NO_THROW(counterSet1 = counterDirectory.RegisterCounterSet(counterSet1Name));
+ BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
+ BOOST_CHECK(counterSet1);
+
+ // Register a category associated to "device1" and "counterset1"
+ const std::string category1Name = "category1";
+ const Category* category1 = nullptr;
+ BOOST_CHECK_NO_THROW(category1 = counterDirectory.RegisterCategory(category1Name));
+ BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
+ BOOST_CHECK(category1);
+
+ // Register a category not associated to "device2" but no counter set
+ const std::string category2Name = "category2";
+ const Category* category2 = nullptr;
+ BOOST_CHECK_NO_THROW(category2 = counterDirectory.RegisterCategory(category2Name));
+ BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
+ BOOST_CHECK(category2);
+
+ uint16_t numberOfCores = 4;
+
+ // Register a counter associated to "category1"
+ const Counter* counter1 = nullptr;
+ BOOST_CHECK_NO_THROW(counter1 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
+ 0,
+ category1Name,
+ 0,
+ 1,
+ 123.45f,
+ "counter1",
+ "counter1description",
+ std::string("counter1units"),
+ numberOfCores));
+ BOOST_CHECK(counterDirectory.GetCounterCount() == 4);
+ BOOST_CHECK(counter1);
+
+ // Register a counter associated to "category1"
+ const Counter* counter2 = nullptr;
+ BOOST_CHECK_NO_THROW(counter2 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
+ 4,
+ category1Name,
+ 1,
+ 0,
+ 330.1245656765f,
+ "counter2",
+ "counter2description",
+ std::string("counter2units"),
+ armnn::EmptyOptional(),
+ device2->m_Uid,
+ 0));
+ BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
+ BOOST_CHECK(counter2);
+
+ // Register a counter associated to "category2"
+ const Counter* counter3 = nullptr;
+ BOOST_CHECK_NO_THROW(counter3 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
+ 5,
+ category2Name,
+ 1,
+ 1,
+ 0.0000045399f,
+ "counter3",
+ "counter3description",
+ armnn::EmptyOptional(),
+ numberOfCores,
+ device2->m_Uid,
+ counterSet1->m_Uid));
+ BOOST_CHECK(counterDirectory.GetCounterCount() == 9);
+ BOOST_CHECK(counter3);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_NO_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory));
+
+ // Get the readable buffer
+ auto readBuffer = mockBuffer.GetReadableBuffer();
+
+ // Check the packet header
+ const uint32_t packetHeaderWord0 = ReadUint32(readBuffer, 0);
+ const uint32_t packetHeaderWord1 = ReadUint32(readBuffer, 4);
+ BOOST_TEST(((packetHeaderWord0 >> 26) & 0x3F) == 0); // packet_family
+ BOOST_TEST(((packetHeaderWord0 >> 16) & 0x3FF) == 2); // packet_id
+ BOOST_TEST(packetHeaderWord1 == 432); // data_length
+
+ // Check the body header
+ const uint32_t bodyHeaderWord0 = ReadUint32(readBuffer, 8);
+ const uint32_t bodyHeaderWord1 = ReadUint32(readBuffer, 12);
+ const uint32_t bodyHeaderWord2 = ReadUint32(readBuffer, 16);
+ const uint32_t bodyHeaderWord3 = ReadUint32(readBuffer, 20);
+ const uint32_t bodyHeaderWord4 = ReadUint32(readBuffer, 24);
+ const uint32_t bodyHeaderWord5 = ReadUint32(readBuffer, 28);
+ const uint16_t deviceRecordCount = static_cast<uint16_t>(bodyHeaderWord0 >> 16);
+ const uint16_t counterSetRecordCount = static_cast<uint16_t>(bodyHeaderWord2 >> 16);
+ const uint16_t categoryRecordCount = static_cast<uint16_t>(bodyHeaderWord4 >> 16);
+ BOOST_TEST(deviceRecordCount == 2); // device_records_count
+ BOOST_TEST(bodyHeaderWord1 == bodyHeaderSize * 4); // device_records_pointer_table_offset
+ BOOST_TEST(counterSetRecordCount == 1); // counter_set_count
+ BOOST_TEST(bodyHeaderWord3 == 8 + bodyHeaderSize * 4); // counter_set_pointer_table_offset
+ BOOST_TEST(categoryRecordCount == 2); // categories_count
+ BOOST_TEST(bodyHeaderWord5 == 12 + bodyHeaderSize * 4); // categories_pointer_table_offset
+
+ // Check the device records pointer table
+ const uint32_t deviceRecordOffset0 = ReadUint32(readBuffer, 32);
+ const uint32_t deviceRecordOffset1 = ReadUint32(readBuffer, 36);
+ BOOST_TEST(deviceRecordOffset0 == 20); // Device record offset for "device1"
+ BOOST_TEST(deviceRecordOffset1 == 40); // Device record offset for "device2"
+
+ // Check the counter set pointer table
+ const uint32_t counterSetRecordOffset0 = ReadUint32(readBuffer, 40);
+ BOOST_TEST(counterSetRecordOffset0 == 52); // Counter set record offset for "counterset1"
+
+ // Check the category pointer table
+ const uint32_t categoryRecordOffset0 = ReadUint32(readBuffer, 44);
+ const uint32_t categoryRecordOffset1 = ReadUint32(readBuffer, 48);
+ BOOST_TEST(categoryRecordOffset0 == 72); // Category record offset for "category1"
+ BOOST_TEST(categoryRecordOffset1 == 176); // Category record offset for "category2"
+
+ // Get the device record pool offset
+ const uint32_t uint32_t_size = sizeof(uint32_t);
+ const uint32_t packetHeaderSize = 2u * uint32_t_size;
+
+ // Device record structure/collection used for testing
+ struct DeviceRecord
+ {
+ uint16_t uid;
+ uint16_t cores;
+ uint32_t name_offset;
+ uint32_t name_length;
+ std::string name;
+ };
+ std::vector<DeviceRecord> deviceRecords;
+ const uint32_t deviceRecordsPointerTableOffset = packetHeaderSize +
+ bodyHeaderWord1; // device_records_pointer_table_offset
+
+ const unsigned char* readData = readBuffer->GetReadableData();
+
+ uint32_t offset = 0;
+ std::vector<uint32_t> data(800);
+
+ for (uint32_t i = 0; i < 800; i+=uint32_t_size)
+ {
+ data[i] = ReadUint32(readBuffer, offset);
+ offset += uint32_t_size;
}
- void SendCounterDirectoryPacket(const Category& category, const std::vector<Counter>& counters) override
+ std::vector<uint32_t> deviceRecordOffsets(deviceRecordCount);
+ offset = deviceRecordsPointerTableOffset;
+ for (uint32_t i = 0; i < deviceRecordCount; ++i)
{
- std::string message("SendCounterDirectoryPacket");
- unsigned int reserved = 0;
- unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
- memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
+ // deviceRecordOffset is relative to the start of the deviceRecordsPointerTable
+ deviceRecordOffsets[i] = ReadUint32(readBuffer, offset) + deviceRecordsPointerTableOffset;
+ offset += uint32_t_size;
}
- void SendPeriodicCounterCapturePacket(uint64_t timestamp, const std::vector<uint32_t>& counterValues,
- const std::vector<uint16_t>& counterUids) override
+ for (uint32_t i = 0; i < deviceRecordCount; i++)
{
- std::string message("SendPeriodicCounterCapturePacket");
- unsigned int reserved = 0;
- unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
- memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
+ // Collect the data for the device record
+ const uint32_t deviceRecordWord0 = ReadUint32(readBuffer, deviceRecordOffsets[i] + 0 * uint32_t_size);
+ const uint32_t deviceRecordWord1 = ReadUint32(readBuffer, deviceRecordOffsets[i] + 1 * uint32_t_size);
+ DeviceRecord deviceRecord;
+ deviceRecord.uid = static_cast<uint16_t>(deviceRecordWord0 >> 16); // uid
+ deviceRecord.cores = static_cast<uint16_t>(deviceRecordWord0); // cores
+ deviceRecord.name_offset = deviceRecordWord1; // name_offset
+
+ uint32_t deviceRecordPoolOffset = deviceRecordOffsets[i] + // Packet body offset
+ deviceRecord.name_offset; // Device name offset
+ uint32_t deviceRecordNameLength = ReadUint32(readBuffer, deviceRecordPoolOffset);
+ deviceRecord.name_length = deviceRecordNameLength; // name_length
+ unsigned char deviceRecordNameNullTerminator = // name null-terminator
+ ReadUint8(readBuffer, deviceRecordPoolOffset + uint32_t_size + deviceRecordNameLength - 1);
+ BOOST_CHECK(deviceRecordNameNullTerminator == '\0');
+ std::vector<unsigned char> deviceRecordNameBuffer(deviceRecord.name_length - 1);
+ std::memcpy(deviceRecordNameBuffer.data(),
+ readData + deviceRecordPoolOffset + uint32_t_size, deviceRecordNameBuffer.size());
+ deviceRecord.name.assign(deviceRecordNameBuffer.begin(), deviceRecordNameBuffer.end()); // name
+
+ deviceRecords.push_back(deviceRecord);
}
- void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
- const std::vector<uint16_t>& selectedCounterIds) override
+ // Check that the device records are correct
+ BOOST_CHECK(deviceRecords.size() == 2);
+ for (const DeviceRecord& deviceRecord : deviceRecords)
{
- std::string message("SendPeriodicCounterSelectionPacket");
- unsigned int reserved = 0;
- unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
- memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
- m_Buffer.Commit(reserved);
+ const Device* device = counterDirectory.GetDevice(deviceRecord.uid);
+ BOOST_CHECK(device);
+ BOOST_CHECK(device->m_Uid == deviceRecord.uid);
+ BOOST_CHECK(device->m_Cores == deviceRecord.cores);
+ BOOST_CHECK(device->m_Name == deviceRecord.name);
}
- void SetReadyToRead() override
- {}
-private:
- IBufferWrapper& m_Buffer;
-};
+ // Counter set record structure/collection used for testing
+ struct CounterSetRecord
+ {
+ uint16_t uid;
+ uint16_t count;
+ uint32_t name_offset;
+ uint32_t name_length;
+ std::string name;
+ };
+ std::vector<CounterSetRecord> counterSetRecords;
+ const uint32_t counterSetRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
+ bodyHeaderWord3; // counter_set_pointer_table_offset
-BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
+ offset = counterSetRecordsPointerTableOffset;
+ std::vector<uint32_t> counterSetRecordOffsets(counterSetRecordCount);
+
+ for (uint32_t i = 0; i < counterSetRecordCount; ++i)
+ {
+ // counterSetRecordOffset is relative to the start of the dcounterSetRecordsPointerTable
+ counterSetRecordOffsets[i] = ReadUint32(readBuffer, offset) + counterSetRecordsPointerTableOffset;
+ offset += uint32_t_size;
+ }
+
+ for (uint32_t i = 0; i < counterSetRecordCount; i++)
+ {
+ // Collect the data for the counter set record
+ const uint32_t counterSetRecordWord0 = ReadUint32(readBuffer, counterSetRecordOffsets[i] + 0 * uint32_t_size);
+ const uint32_t counterSetRecordWord1 = ReadUint32(readBuffer, counterSetRecordOffsets[i] + 1 * uint32_t_size);
+ CounterSetRecord counterSetRecord;
+ counterSetRecord.uid = static_cast<uint16_t>(counterSetRecordWord0 >> 16); // uid
+ counterSetRecord.count = static_cast<uint16_t>(counterSetRecordWord0); // count
+ counterSetRecord.name_offset = counterSetRecordWord1; // name_offset
+
+ uint32_t counterSetRecordPoolOffset = counterSetRecordOffsets[i] + // Packet body offset
+ counterSetRecord.name_offset; // Counter set name offset
+ uint32_t counterSetRecordNameLength = ReadUint32(readBuffer, counterSetRecordPoolOffset);
+ counterSetRecord.name_length = counterSetRecordNameLength; // name_length
+ unsigned char counterSetRecordNameNullTerminator = // name null-terminator
+ ReadUint8(readBuffer, counterSetRecordPoolOffset + uint32_t_size + counterSetRecordNameLength - 1);
+ BOOST_CHECK(counterSetRecordNameNullTerminator == '\0');
+ std::vector<unsigned char> counterSetRecordNameBuffer(counterSetRecord.name_length - 1);
+ std::memcpy(counterSetRecordNameBuffer.data(),
+ readData + counterSetRecordPoolOffset + uint32_t_size, counterSetRecordNameBuffer.size());
+ counterSetRecord.name.assign(counterSetRecordNameBuffer.begin(), counterSetRecordNameBuffer.end()); // name
+
+ counterSetRecords.push_back(counterSetRecord);
+ }
+
+ // Check that the counter set records are correct
+ BOOST_CHECK(counterSetRecords.size() == 1);
+ for (const CounterSetRecord& counterSetRecord : counterSetRecords)
+ {
+ const CounterSet* counterSet = counterDirectory.GetCounterSet(counterSetRecord.uid);
+ BOOST_CHECK(counterSet);
+ BOOST_CHECK(counterSet->m_Uid == counterSetRecord.uid);
+ BOOST_CHECK(counterSet->m_Count == counterSetRecord.count);
+ BOOST_CHECK(counterSet->m_Name == counterSetRecord.name);
+ }
+
+ // Event record structure/collection used for testing
+ struct EventRecord
+ {
+ uint16_t counter_uid;
+ uint16_t max_counter_uid;
+ uint16_t device;
+ uint16_t counter_set;
+ uint16_t counter_class;
+ uint16_t interpolation;
+ double multiplier;
+ uint32_t name_offset;
+ uint32_t name_length;
+ std::string name;
+ uint32_t description_offset;
+ uint32_t description_length;
+ std::string description;
+ uint32_t units_offset;
+ uint32_t units_length;
+ std::string units;
+ };
+ // Category record structure/collection used for testing
+ struct CategoryRecord
+ {
+ uint16_t event_count;
+ uint32_t event_pointer_table_offset;
+ uint32_t name_offset;
+ uint32_t name_length;
+ std::string name;
+ std::vector<uint32_t> event_pointer_table;
+ std::vector<EventRecord> event_records;
+ };
+ std::vector<CategoryRecord> categoryRecords;
+ const uint32_t categoryRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
+ bodyHeaderWord5; // categories_pointer_table_offset
+
+ offset = categoryRecordsPointerTableOffset;
+ std::vector<uint32_t> categoryRecordOffsets(categoryRecordCount);
+ for (uint32_t i = 0; i < categoryRecordCount; ++i)
+ {
+ // categoryRecordOffset is relative to the start of the categoryRecordsPointerTable
+ categoryRecordOffsets[i] = ReadUint32(readBuffer, offset) + categoryRecordsPointerTableOffset;
+ offset += uint32_t_size;
+ }
+
+ for (uint32_t i = 0; i < categoryRecordCount; i++)
+ {
+ // Collect the data for the category record
+ const uint32_t categoryRecordWord1 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 0 * uint32_t_size);
+ const uint32_t categoryRecordWord2 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 1 * uint32_t_size);
+ const uint32_t categoryRecordWord3 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 2 * uint32_t_size);
+ CategoryRecord categoryRecord;
+ categoryRecord.event_count = static_cast<uint16_t>(categoryRecordWord1 >> 16); // event_count
+ categoryRecord.event_pointer_table_offset = categoryRecordWord2; // event_pointer_table_offset
+ categoryRecord.name_offset = categoryRecordWord3; // name_offset
+
+ uint32_t categoryRecordNameLength = ReadUint32(readBuffer,
+ categoryRecordOffsets[i] + categoryRecord.name_offset);
+ categoryRecord.name_length = categoryRecordNameLength; // name_length
+ unsigned char categoryRecordNameNullTerminator =
+ ReadUint8(readBuffer,
+ categoryRecordOffsets[i] +
+ categoryRecord.name_offset +
+ uint32_t_size +
+ categoryRecordNameLength - 1); // name null-terminator
+ BOOST_CHECK(categoryRecordNameNullTerminator == '\0');
+ std::vector<unsigned char> categoryRecordNameBuffer(categoryRecord.name_length - 1);
+ std::memcpy(categoryRecordNameBuffer.data(),
+ readData +
+ categoryRecordOffsets[i] +
+ categoryRecord.name_offset +
+ uint32_t_size,
+ categoryRecordNameBuffer.size());
+ categoryRecord.name.assign(categoryRecordNameBuffer.begin(), categoryRecordNameBuffer.end()); // name
+
+ categoryRecord.event_pointer_table.resize(categoryRecord.event_count);
+ offset = categoryRecordOffsets[i] + categoryRecord.event_pointer_table_offset;
+ for (uint32_t eventOffsetIndex = 0; eventOffsetIndex < categoryRecord.event_count; ++eventOffsetIndex)
+ {
+ // eventRecordOffset is relative to the start of the event pointer table
+ categoryRecord.event_pointer_table[eventOffsetIndex] = ReadUint32(readBuffer, offset) +
+ categoryRecordOffsets[i] +
+ categoryRecord.event_pointer_table_offset;
+ offset += uint32_t_size;
+ }
+
+ for (uint32_t eventIndex = 0; eventIndex < categoryRecord.event_count; eventIndex++)
+ {
+ const uint32_t eventOffset = categoryRecord.event_pointer_table[eventIndex];
+ // Collect the data for the event record
+ const uint32_t eventRecordWord0 = ReadUint32(readBuffer, eventOffset + 0 * uint32_t_size);
+ const uint32_t eventRecordWord1 = ReadUint32(readBuffer, eventOffset + 1 * uint32_t_size);
+ const uint32_t eventRecordWord2 = ReadUint32(readBuffer, eventOffset + 2 * uint32_t_size);
+ const uint64_t eventRecordWord34 = ReadUint64(readBuffer, eventOffset + 3 * uint32_t_size);
+ const uint32_t eventRecordWord5 = ReadUint32(readBuffer, eventOffset + 5 * uint32_t_size);
+ const uint32_t eventRecordWord6 = ReadUint32(readBuffer, eventOffset + 6 * uint32_t_size);
+ const uint32_t eventRecordWord7 = ReadUint32(readBuffer, eventOffset + 7 * uint32_t_size);
+
+ EventRecord eventRecord;
+ eventRecord.counter_uid = static_cast<uint16_t>(eventRecordWord0); // counter_uid
+ eventRecord.max_counter_uid = static_cast<uint16_t>(eventRecordWord0 >> 16); // max_counter_uid
+ eventRecord.device = static_cast<uint16_t>(eventRecordWord1 >> 16); // device
+ eventRecord.counter_set = static_cast<uint16_t>(eventRecordWord1); // counter_set
+ eventRecord.counter_class = static_cast<uint16_t>(eventRecordWord2 >> 16); // class
+ eventRecord.interpolation = static_cast<uint16_t>(eventRecordWord2); // interpolation
+ std::memcpy(&eventRecord.multiplier, &eventRecordWord34, sizeof(eventRecord.multiplier)); // multiplier
+ eventRecord.name_offset = static_cast<uint32_t>(eventRecordWord5); // name_offset
+ eventRecord.description_offset = static_cast<uint32_t>(eventRecordWord6); // description_offset
+ eventRecord.units_offset = static_cast<uint32_t>(eventRecordWord7); // units_offset
+
+ uint32_t eventRecordNameLength = ReadUint32(readBuffer, eventOffset + eventRecord.name_offset);
+ eventRecord.name_length = eventRecordNameLength; // name_length
+ unsigned char eventRecordNameNullTerminator =
+ ReadUint8(readBuffer,
+ eventOffset +
+ eventRecord.name_offset +
+ uint32_t_size +
+ eventRecordNameLength - 1); // name null-terminator
+ BOOST_CHECK(eventRecordNameNullTerminator == '\0');
+ std::vector<unsigned char> eventRecordNameBuffer(eventRecord.name_length - 1);
+ std::memcpy(eventRecordNameBuffer.data(),
+ readData +
+ eventOffset +
+ eventRecord.name_offset +
+ uint32_t_size,
+ eventRecordNameBuffer.size());
+ eventRecord.name.assign(eventRecordNameBuffer.begin(), eventRecordNameBuffer.end()); // name
+
+ uint32_t eventRecordDescriptionLength = ReadUint32(readBuffer,
+ eventOffset + eventRecord.description_offset);
+ eventRecord.description_length = eventRecordDescriptionLength; // description_length
+ unsigned char eventRecordDescriptionNullTerminator =
+ ReadUint8(readBuffer,
+ eventOffset +
+ eventRecord.description_offset +
+ uint32_t_size +
+ eventRecordDescriptionLength - 1); // description null-terminator
+ BOOST_CHECK(eventRecordDescriptionNullTerminator == '\0');
+ std::vector<unsigned char> eventRecordDescriptionBuffer(eventRecord.description_length - 1);
+ std::memcpy(eventRecordDescriptionBuffer.data(),
+ readData +
+ eventOffset +
+ eventRecord.description_offset +
+ uint32_t_size,
+ eventRecordDescriptionBuffer.size());
+ eventRecord.description.assign(eventRecordDescriptionBuffer.begin(),
+ eventRecordDescriptionBuffer.end()); // description
+
+ if (eventRecord.units_offset > 0)
+ {
+ uint32_t eventRecordUnitsLength = ReadUint32(readBuffer,
+ eventOffset + eventRecord.units_offset);
+ eventRecord.units_length = eventRecordUnitsLength; // units_length
+ unsigned char eventRecordUnitsNullTerminator =
+ ReadUint8(readBuffer,
+ eventOffset +
+ eventRecord.units_offset +
+ uint32_t_size +
+ eventRecordUnitsLength - 1); // units null-terminator
+ BOOST_CHECK(eventRecordUnitsNullTerminator == '\0');
+ std::vector<unsigned char> eventRecordUnitsBuffer(eventRecord.units_length - 1);
+ std::memcpy(eventRecordUnitsBuffer.data(),
+ readData +
+ eventOffset +
+ eventRecord.units_offset +
+ uint32_t_size,
+ eventRecordUnitsBuffer.size());
+ eventRecord.units.assign(eventRecordUnitsBuffer.begin(), eventRecordUnitsBuffer.end()); // units
+ }
+
+ categoryRecord.event_records.push_back(eventRecord);
+ }
+
+ categoryRecords.push_back(categoryRecord);
+ }
+
+ // Check that the category records are correct
+ BOOST_CHECK(categoryRecords.size() == 2);
+ for (const CategoryRecord& categoryRecord : categoryRecords)
+ {
+ const Category* category = counterDirectory.GetCategory(categoryRecord.name);
+ BOOST_CHECK(category);
+ BOOST_CHECK(category->m_Name == categoryRecord.name);
+ BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
+ BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
+
+ // Check that the event records are correct
+ for (const EventRecord& eventRecord : categoryRecord.event_records)
+ {
+ const Counter* counter = counterDirectory.GetCounter(eventRecord.counter_uid);
+ BOOST_CHECK(counter);
+ BOOST_CHECK(counter->m_MaxCounterUid == eventRecord.max_counter_uid);
+ BOOST_CHECK(counter->m_DeviceUid == eventRecord.device);
+ BOOST_CHECK(counter->m_CounterSetUid == eventRecord.counter_set);
+ BOOST_CHECK(counter->m_Class == eventRecord.counter_class);
+ BOOST_CHECK(counter->m_Interpolation == eventRecord.interpolation);
+ BOOST_CHECK(counter->m_Multiplier == eventRecord.multiplier);
+ BOOST_CHECK(counter->m_Name == eventRecord.name);
+ BOOST_CHECK(counter->m_Description == eventRecord.description);
+ BOOST_CHECK(counter->m_Units == eventRecord.units);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest3)
+{
+ // Using a mock counter directory that allows to register invalid objects
+ MockCounterDirectory counterDirectory;
+
+ // Register an invalid device
+ const std::string deviceName = "inv@lid dev!c€";
+ const Device* device = nullptr;
+ BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
+ BOOST_CHECK(device);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest4)
+{
+ // Using a mock counter directory that allows to register invalid objects
+ MockCounterDirectory counterDirectory;
+
+ // Register an invalid counter set
+ const std::string counterSetName = "inv@lid count€rs€t";
+ const CounterSet* counterSet = nullptr;
+ BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
+ BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
+ BOOST_CHECK(counterSet);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest5)
+{
+ // Using a mock counter directory that allows to register invalid objects
+ MockCounterDirectory counterDirectory;
+
+ // Register an invalid category
+ const std::string categoryName = "c@t€gory";
+ const Category* category = nullptr;
+ BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
+ BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
+ BOOST_CHECK(category);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest6)
+{
+ // Using a mock counter directory that allows to register invalid objects
+ MockCounterDirectory counterDirectory;
+
+ // Register an invalid device
+ const std::string deviceName = "inv@lid dev!c€";
+ const Device* device = nullptr;
+ BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
+ BOOST_CHECK(device);
+
+ // Register an invalid counter set
+ const std::string counterSetName = "inv@lid count€rs€t";
+ const CounterSet* counterSet = nullptr;
+ BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
+ BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
+ BOOST_CHECK(counterSet);
+
+ // Register an invalid category associated to an invalid device and an invalid counter set
+ const std::string categoryName = "c@t€gory";
+ const Category* category = nullptr;
+ BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
+ BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
+ BOOST_CHECK(category);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest7)
+{
+ // Using a mock counter directory that allows to register invalid objects
+ MockCounterDirectory counterDirectory;
+
+ // Register an valid device
+ const std::string deviceName = "valid device";
+ const Device* device = nullptr;
+ BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
+ BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
+ BOOST_CHECK(device);
+
+ // Register an valid counter set
+ const std::string counterSetName = "valid counterset";
+ const CounterSet* counterSet = nullptr;
+ BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
+ BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
+ BOOST_CHECK(counterSet);
+
+ // Register an valid category associated to a valid device and a valid counter set
+ const std::string categoryName = "category";
+ const Category* category = nullptr;
+ BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
+ BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
+ BOOST_CHECK(category);
+
+ // Register an invalid counter associated to a valid category
+ const Counter* counter = nullptr;
+ BOOST_CHECK_NO_THROW(counter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
+ 0,
+ categoryName,
+ 0,
+ 1,
+ 123.45f,
+ "counter",
+ "counter description",
+ std::string("invalid counter units"),
+ 5,
+ device->m_Uid,
+ counterSet->m_Uid));
+ BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
+ BOOST_CHECK(counter);
+
+ // Buffer with enough space
+ MockBufferManager mockBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+ BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadTest0)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetActiveProfilingState(profilingStateMachine);
+
+ MockProfilingConnection mockProfilingConnection;
+ MockStreamCounterBuffer mockStreamCounterBuffer(0);
+ SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
+ SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
+
+ // Try to start the send thread many times, it must only start once
+
+ sendThread.Start(mockProfilingConnection);
+ BOOST_CHECK(sendThread.IsRunning());
+ sendThread.Start(mockProfilingConnection);
+ sendThread.Start(mockProfilingConnection);
+ sendThread.Start(mockProfilingConnection);
+ sendThread.Start(mockProfilingConnection);
+ BOOST_CHECK(sendThread.IsRunning());
+
+ sendThread.Stop();
+ BOOST_CHECK(!sendThread.IsRunning());
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadTest1)
{
- unsigned int size = 0;
+ ProfilingStateMachine profilingStateMachine;
+ SetActiveProfilingState(profilingStateMachine);
+
+ unsigned int totalWrittenSize = 0;
- MockBuffer mockBuffer;
- MockSendCounterPacket sendCounterPacket(mockBuffer);
+ MockProfilingConnection mockProfilingConnection;
+ MockStreamCounterBuffer mockStreamCounterBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
+ SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+ // Interleaving writes and reads to/from the buffer with pauses to test that the send thread actually waits for
+ // something to become available for reading
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ CounterDirectory counterDirectory;
sendCounterPacket.SendStreamMetaDataPacket();
- const char* buffer = reinterpret_cast<const char*>(mockBuffer.GetReadBuffer(size));
- BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
+ totalWrittenSize += GetStreamMetaDataPacketSize();
- Category category;
- std::vector<Counter> counters;
- sendCounterPacket.SendCounterDirectoryPacket(category, counters);
+ sendThread.SetReadyToRead();
- BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
- uint64_t timestamp = 0;
- std::vector<uint32_t> counterValues;
- std::vector<uint16_t> counterUids;
- sendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, counterValues, counterUids);
+ sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
- BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
+ // Get the size of the Counter Directory Packet
+ unsigned int counterDirectoryPacketSize = 32;
+ totalWrittenSize += counterDirectoryPacketSize;
- uint32_t capturePeriod = 0;
- std::vector<uint16_t> selectedCounterIds;
- sendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
+ sendThread.SetReadyToRead();
- BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
+ {
+ { 1u, 23u },
+ { 33u, 1207623u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ unsigned int periodicCounterCapturePacketSize = 28;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
+ {
+ { 211u, 923u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 22;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
+ {
+ { 555u, 23u },
+ { 556u, 6u },
+ { 557u, 893454u },
+ { 558u, 1456623u },
+ { 559u, 571090u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 46;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
+ {
+ { 88u, 11u },
+ { 96u, 22u },
+ { 97u, 33u },
+ { 999u, 444u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 40;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 30;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
+ // read all what's remaining in the buffer
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendThread.Stop();
+
+ BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadTest2)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetActiveProfilingState(profilingStateMachine);
+
+ unsigned int totalWrittenSize = 0;
+
+ MockProfilingConnection mockProfilingConnection;
+ MockStreamCounterBuffer mockStreamCounterBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
+ SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // Adding many spurious "ready to read" signals throughout the test to check that the send thread is
+ // capable of handling unnecessary read requests
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendThread.SetReadyToRead();
+
+ CounterDirectory counterDirectory;
+ sendCounterPacket.SendStreamMetaDataPacket();
+
+ totalWrittenSize += GetStreamMetaDataPacketSize();
+
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
+
+ // Get the size of the Counter Directory Packet
+ unsigned int counterDirectoryPacketSize = 32;
+ totalWrittenSize += counterDirectoryPacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
+ {
+ { 1u, 23u },
+ { 33u, 1207623u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ unsigned int periodicCounterCapturePacketSize = 28;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
+ {
+ { 211u, 923u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 22;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
+ {
+ { 555u, 23u },
+ { 556u, 6u },
+ { 557u, 893454u },
+ { 558u, 1456623u },
+ { 559u, 571090u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 46;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
+ {
+ { 88u, 11u },
+ { 96u, 22u },
+ { 97u, 33u },
+ { 999u, 444u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 40;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
+
+ sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 30;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
+ // read all what's remaining in the buffer
+ sendThread.Stop();
+
+ BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadTest3)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetActiveProfilingState(profilingStateMachine);
+
+ unsigned int totalWrittenSize = 0;
+
+ MockProfilingConnection mockProfilingConnection;
+ MockStreamCounterBuffer mockStreamCounterBuffer(1024);
+ SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
+ SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // Not using pauses or "grace periods" to stress test the send thread
+
+ sendThread.SetReadyToRead();
+
+ CounterDirectory counterDirectory;
+ sendCounterPacket.SendStreamMetaDataPacket();
+
+ totalWrittenSize += GetStreamMetaDataPacketSize();
+
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
+
+ // Get the size of the Counter Directory Packet
+ unsigned int counterDirectoryPacketSize =32;
+ totalWrittenSize += counterDirectoryPacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
+ {
+ { 1u, 23u },
+ { 33u, 1207623u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ unsigned int periodicCounterCapturePacketSize = 28;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
+ {
+ { 211u, 923u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 22;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
+ {
+ { 555u, 23u },
+ { 556u, 6u },
+ { 557u, 893454u },
+ { 558u, 1456623u },
+ { 559u, 571090u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 46;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
+ {
+ { 88u, 11u },
+ { 96u, 22u },
+ { 97u, 33u },
+ { 999u, 444u }
+ });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 40;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+ sendThread.SetReadyToRead();
+ sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
+
+ // Get the size of the Periodic Counter Capture Packet
+ periodicCounterCapturePacketSize = 30;
+ totalWrittenSize += periodicCounterCapturePacketSize;
+
+ sendThread.SetReadyToRead();
+
+ // Abruptly terminating the send thread, the amount of data sent may be less that the amount written (the send
+ // thread is not guaranteed to flush the buffer)
+ sendThread.Stop();
+
+ BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() <= totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= totalWrittenSize);
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetReadableSize());
+ BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetCommittedSize());
+}
+
+BOOST_AUTO_TEST_CASE(SendCounterPacketTestWithSendThread)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetWaitingForAckProfilingState(profilingStateMachine);
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(1, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
+ sendThread.Start(mockProfilingConnection);
+
+ unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
+
+ sendThread.Stop();
+
+ // check for packet in ProfilingConnection
+ BOOST_CHECK(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) == 1);
+
+ SetActiveProfilingState(profilingStateMachine);
+ sendThread.Start(mockProfilingConnection);
+
+ // SendCounterDirectoryPacket
+ CounterDirectory counterDirectory;
+ sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
+
+ sendThread.Stop();
+ unsigned int counterDirectoryPacketSize = 32;
+ // check for packet in ProfilingConnection
+ BOOST_CHECK(mockProfilingConnection.CheckForPacket(
+ {PacketType::CounterDirectory, counterDirectoryPacketSize}) == 1);
+
+ sendThread.Start(mockProfilingConnection);
+
+ // SendPeriodicCounterCapturePacket
+ sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
+ {
+ { 1u, 23u },
+ { 33u, 1207623u }
+ });
+
+ sendThread.Stop();
+
+ unsigned int periodicCounterCapturePacketSize = 28;
+ BOOST_CHECK(mockProfilingConnection.CheckForPacket(
+ {PacketType::PeriodicCounterCapture, periodicCounterCapturePacketSize}) == 1);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadBufferTest)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetActiveProfilingState(profilingStateMachine);
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(3, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
+ sendThread.Start(mockProfilingConnection);
+
+ // SendStreamMetaDataPacket
+ sendCounterPacket.SendStreamMetaDataPacket();
+
+ // Read data from the buffer
+ // Buffer should become readable after commit by SendStreamMetaDataPacket
+ auto packetBuffer = bufferManager.GetReadableBuffer();
+ BOOST_TEST(packetBuffer.get());
+
+ unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
+ BOOST_TEST(packetBuffer->GetSize() == streamMetadataPacketsize);
+
+ // Recommit to be read by sendCounterPacket
+ bufferManager.Commit(packetBuffer, streamMetadataPacketsize);
+
+ // SendCounterDirectoryPacket
+ CounterDirectory counterDirectory;
+ sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
+
+ // SendPeriodicCounterCapturePacket
+ sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
+ {
+ { 1u, 23u },
+ { 33u, 1207623u }
+ });
+
+ sendThread.Stop();
+
+ // The buffer is read by the send thread so it should not be in the readable buffer.
+ auto readBuffer = bufferManager.GetReadableBuffer();
+ BOOST_TEST(!readBuffer);
+
+ // Successfully reserved the buffer with requested size
+ unsigned int reservedSize = 0;
+ auto reservedBuffer = bufferManager.Reserve(512, reservedSize);
+ BOOST_TEST(reservedSize == 512);
+ BOOST_TEST(reservedBuffer.get());
+
+ const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
+ const auto metaDataPacketCount =
+ mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize});
+
+ BOOST_TEST(metaDataPacketCount >= 1);
+ BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::CounterDirectory, 32}) == 1);
+ BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::PeriodicCounterCapture, 28}) == 1);
+ // Check that we only received the packets we expected
+ BOOST_TEST(metaDataPacketCount + 2 == writtenDataSize);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket1)
+{
+ ProfilingStateMachine profilingStateMachine;
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(3, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // The profiling state is set to "Uninitialized", so the send thread should throw an exception
+ BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket2)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetNotConnectedProfilingState(profilingStateMachine);
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(3, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // The profiling state is set to "NotConnected", so the send thread should throw an exception
+ BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket3)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetWaitingForAckProfilingState(profilingStateMachine);
+
+ unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(3, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
+ // Wait for sendThread to join
+ BOOST_CHECK_NO_THROW(sendThread.Stop());
+
+ // Check that the buffer contains at least one Stream Metadata packet and no other packets
+ const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
+
+ BOOST_TEST(writtenDataSize >= 1);
+ BOOST_TEST(mockProfilingConnection.CheckForPacket(
+ {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
+}
+
+BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket4)
+{
+ ProfilingStateMachine profilingStateMachine;
+ SetWaitingForAckProfilingState(profilingStateMachine);
+
+ unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
+
+ MockProfilingConnection mockProfilingConnection;
+ BufferManager bufferManager(3, 1024);
+ SendCounterPacket sendCounterPacket(bufferManager);
+ SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
+ sendThread.Start(mockProfilingConnection);
+
+ // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
+ // Wait for sendThread to join
+ sendThread.Stop();
+
+ sendThread.Start(mockProfilingConnection);
+ // Check that the profiling state is still "WaitingForAck"
+ BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
+
+ // Check that the buffer contains at least one Stream Metadata packet
+ BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) >= 1);
+
+ mockProfilingConnection.Clear();
+
+ sendThread.Stop();
+ sendThread.Start(mockProfilingConnection);
+
+ // Try triggering a new buffer read
+ sendThread.SetReadyToRead();
+
+ // Wait for sendThread to join
+ BOOST_CHECK_NO_THROW(sendThread.Stop());
+
+ // Check that the profiling state is still "WaitingForAck"
+ BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
+
+ // Check that the buffer contains at least one Stream Metadata packet and no other packets
+ const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
+ BOOST_TEST(writtenDataSize >= 1);
+ BOOST_TEST(mockProfilingConnection.CheckForPacket(
+ {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
}
BOOST_AUTO_TEST_SUITE_END()