aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/test/ProfilingTests.cpp
diff options
context:
space:
mode:
authorMatteo Martincigh <matteo.martincigh@arm.com>2019-10-10 14:08:21 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-10-11 16:33:29 +0100
commite848538efbdf01aa0b067da942c3c214f8e62826 (patch)
treed700239f1316a098849fcfc39ec70e926f86fd62 /src/profiling/test/ProfilingTests.cpp
parentf982deaefbe5fe5814487b27f7099829839b8666 (diff)
downloadarmnn-e848538efbdf01aa0b067da942c3c214f8e62826.tar.gz
IVGCVSW-3964 Implement the Periodic Counter Selection command handler
* Improved the PeriodicCounterPacket class to handle errors properly * Improved the PeriodicCounterSelectionCommandHandler to handle invalid counter UIDs in the selection packet * Added the Periodic Counter Selection command handler to the ProfilingService class * Code refactoring and added comments * Added WaitForPacketSent method to the SendCounterPacket class to allow waiting for the packets to be sent (useful in the unit tests) * Added unit tests and updated the old ones accordingly * Fixed threading issues with a number of unit tests Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com> Change-Id: I271b7b0bfa801d88fe1725b934d24e30cd839ed7
Diffstat (limited to 'src/profiling/test/ProfilingTests.cpp')
-rw-r--r--src/profiling/test/ProfilingTests.cpp584
1 files changed, 545 insertions, 39 deletions
diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp
index 27bacf7145..554b7e1936 100644
--- a/src/profiling/test/ProfilingTests.cpp
+++ b/src/profiling/test/ProfilingTests.cpp
@@ -35,6 +35,7 @@
#include <limits>
#include <map>
#include <random>
+#include <iostream>
using namespace armnn::profiling;
@@ -1691,11 +1692,19 @@ BOOST_AUTO_TEST_CASE(CounterSelectionCommandHandlerParseData)
void Stop() override {}
};
+ class TestReadCounterValues : public IReadCounterValues
+ {
+ bool IsCounterRegistered(uint16_t counterUid) const override { return true; }
+ uint16_t GetCounterCount() const override { return 0; }
+ uint32_t GetCounterValue(uint16_t counterUid) const override { return 0; }
+ };
+
const uint32_t packetId = 0x40000;
uint32_t version = 1;
Holder holder;
TestCaptureThread captureThread;
+ TestReadCounterValues readCounterValues;
MockBufferManager mockBuffer(512);
SendCounterPacket sendCounterPacket(profilingStateMachine, mockBuffer);
@@ -1718,16 +1727,29 @@ BOOST_AUTO_TEST_CASE(CounterSelectionCommandHandlerParseData)
Packet packetA(packetId, dataLength1, uniqueData1);
- PeriodicCounterSelectionCommandHandler commandHandler(packetId, version, holder, captureThread,
- sendCounterPacket);
- commandHandler(packetA);
+ PeriodicCounterSelectionCommandHandler commandHandler(packetId,
+ version,
+ holder,
+ captureThread,
+ readCounterValues,
+ sendCounterPacket,
+ profilingStateMachine);
- std::vector<uint16_t> counterIds = holder.GetCaptureData().GetCounterIds();
+ profilingStateMachine.TransitionToState(ProfilingState::Uninitialised);
+ BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
+ profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
+ BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
+ profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
+ BOOST_CHECK_THROW(commandHandler(packetA), armnn::RuntimeException);
+ profilingStateMachine.TransitionToState(ProfilingState::Active);
+ BOOST_CHECK_NO_THROW(commandHandler(packetA));
+
+ const std::vector<uint16_t> counterIdsA = holder.GetCaptureData().GetCounterIds();
BOOST_TEST(holder.GetCaptureData().GetCapturePeriod() == period1);
- BOOST_TEST(counterIds.size() == 2);
- BOOST_TEST(counterIds[0] == 4000);
- BOOST_TEST(counterIds[1] == 5000);
+ BOOST_TEST(counterIdsA.size() == 2);
+ BOOST_TEST(counterIdsA[0] == 4000);
+ BOOST_TEST(counterIdsA[1] == 5000);
auto readBuffer = mockBuffer.GetReadableBuffer();
@@ -1766,10 +1788,10 @@ BOOST_AUTO_TEST_CASE(CounterSelectionCommandHandlerParseData)
commandHandler(packetB);
- counterIds = holder.GetCaptureData().GetCounterIds();
+ const std::vector<uint16_t> counterIdsB = holder.GetCaptureData().GetCounterIds();
BOOST_TEST(holder.GetCaptureData().GetCapturePeriod() == period2);
- BOOST_TEST(counterIds.size() == 0);
+ BOOST_TEST(counterIdsB.size() == 0);
readBuffer = mockBuffer.GetReadableBuffer();
@@ -2024,35 +2046,40 @@ BOOST_AUTO_TEST_CASE(CheckPeriodicCounterCaptureThread)
public:
CaptureReader() {}
+ bool IsCounterRegistered(uint16_t counterUid) const override
+ {
+ return m_Data.find(counterUid) != m_Data.end();
+ }
+
uint16_t GetCounterCount() const override
{
return boost::numeric_cast<uint16_t>(m_Data.size());
}
- uint32_t GetCounterValue(uint16_t index) const override
+ uint32_t GetCounterValue(uint16_t counterUid) const override
{
- if (m_Data.find(index) == m_Data.end())
+ if (m_Data.find(counterUid) == m_Data.end())
{
return 0;
}
- return m_Data.at(index);
+ return m_Data.at(counterUid).load();
}
- void SetCounterValue(uint16_t index, uint32_t value)
+ void SetCounterValue(uint16_t counterUid, uint32_t value)
{
- if (m_Data.find(index) == m_Data.end())
+ if (m_Data.find(counterUid) == m_Data.end())
{
- m_Data.insert(std::pair<uint16_t, uint32_t>(index, value));
+ m_Data.insert(std::make_pair(counterUid, value));
}
else
{
- m_Data.at(index) = value;
+ m_Data.at(counterUid).store(value);
}
}
private:
- std::unordered_map<uint16_t, uint32_t> m_Data;
+ std::unordered_map<uint16_t, std::atomic<uint32_t>> m_Data;
};
ProfilingStateMachine profilingStateMachine;
@@ -2261,19 +2288,23 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadConnectionAcknowledgedPacket)
// Bring the profiling service to the "WaitingForAck" state
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
- profilingService.Update();
+ profilingService.Update(); // Initialize the counter directory
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
- profilingService.Update();
- BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
- profilingService.Update();
-
- // Wait for a bit to make sure that we get the packet
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ profilingService.Update();// Create the profiling connection
// Get the mock profiling connection
MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
BOOST_CHECK(mockProfilingConnection);
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update();
+
+ // Wait for the Stream Metadata packet to be sent
+ helper.WaitForProfilingPacketsSent();
+
// Check that the mock profiling connection contains one Stream Metadata packet
const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
BOOST_TEST(writtenData.size() == 1);
@@ -2330,19 +2361,23 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodConnectionAcknowledgedPacket)
// Bring the profiling service to the "WaitingForAck" state
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
- profilingService.Update();
+ profilingService.Update(); // Initialize the counter directory
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
- profilingService.Update();
- BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
- profilingService.Update();
-
- // Wait for a bit to make sure that we get the packet
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ profilingService.Update(); // Create the profiling connection
// Get the mock profiling connection
MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
BOOST_CHECK(mockProfilingConnection);
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet to be sent
+ helper.WaitForProfilingPacketsSent();
+
// Check that the mock profiling connection contains one Stream Metadata packet
const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
BOOST_TEST(writtenData.size() == 1);
@@ -2403,7 +2438,13 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadRequestCounterDirectoryPacket)
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
profilingService.Update(); // Create the profiling connection
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
- profilingService.Update(); // Start the threads
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
helper.ForceTransitionToState(ProfilingState::Active);
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
@@ -2411,6 +2452,9 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadRequestCounterDirectoryPacket)
MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
BOOST_CHECK(mockProfilingConnection);
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
// Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
// reply from an external profiling service
@@ -2437,7 +2481,7 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadRequestCounterDirectoryPacket)
// Check that the expected error has occurred and logged to the standard output
BOOST_CHECK(boost::contains(ss.str(), "Functor with requested PacketId=123 and Version=4194304 does not exist"));
- // The Connection Acknowledged Command Handler should not have updated the profiling state
+ // The Request Counter Directory Command Handler should not have updated the profiling state
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
// Reset the profiling service to stop any running thread
@@ -2462,7 +2506,13 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodRequestCounterDirectoryPacket)
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
profilingService.Update(); // Create the profiling connection
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
- profilingService.Update(); // Start the threads
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
helper.ForceTransitionToState(ProfilingState::Active);
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
@@ -2470,6 +2520,9 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodRequestCounterDirectoryPacket)
MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
BOOST_CHECK(mockProfilingConnection);
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
// Write a valid "Request Counter Directory" packet into the mock profiling connection, to simulate a valid
// reply from an external profiling service
@@ -2489,17 +2542,470 @@ BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodRequestCounterDirectoryPacket)
// Write the packet to the mock profiling connection
mockProfilingConnection->WritePacket(std::move(requestCounterDirectoryPacket));
+ // Wait for the Counter Directory packet to be sent
+ helper.WaitForProfilingPacketsSent();
+
+ // Check that the mock profiling connection contains one Counter Directory packet
+ const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
+ BOOST_TEST(writtenData.size() == 1);
+ BOOST_TEST(writtenData[0] == 416); // The size of the expected Counter Directory packet
+
+ // The Request Counter Directory Command Handler should not have updated the profiling state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Reset the profiling service to stop any running thread
+ options.m_EnableProfiling = false;
+ profilingService.ResetExternalProfilingOptions(options, true);
+}
+
+BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadPeriodicCounterSelectionPacket)
+{
+ // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
+ LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
+
+ // Swap the profiling connection factory in the profiling service instance with our mock one
+ SwapProfilingConnectionFactoryHelper helper;
+
+ // Redirect the standard output to a local stream so that we can parse the warning message
+ std::stringstream ss;
+ StreamRedirector streamRedirector(std::cout, ss.rdbuf());
+
+ // Reset the profiling service to the uninitialized state
+ armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
+ options.m_EnableProfiling = true;
+ ProfilingService& profilingService = ProfilingService::Instance();
+ profilingService.ResetExternalProfilingOptions(options, true);
+
+ // Bring the profiling service to the "Active" state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
+ profilingService.Update(); // Initialize the counter directory
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
+ profilingService.Update(); // Create the profiling connection
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
+ helper.ForceTransitionToState(ProfilingState::Active);
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Get the mock profiling connection
+ MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
+ BOOST_CHECK(mockProfilingConnection);
+
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
+ // external profiling service
+
+ // Periodic Counter Selection packet header:
+ // 26:31 [6] packet_family: Control Packet Family, value 0b000000
+ // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
+ // 8:15 [8] reserved: Reserved, value 0b00000000
+ // 0:7 [8] reserved: Reserved, value 0b00000000
+ uint32_t packetFamily = 0;
+ uint32_t packetId = 999; // Wrong packet id!!!
+ uint32_t header = ((packetFamily & 0x0000003F) << 26) |
+ ((packetId & 0x000003FF) << 16);
+
+ // Create the Periodic Counter Selection packet
+ Packet periodicCounterSelectionPacket(header); // Length == 0, this will disable the collection of counters
+
+ // Write the packet to the mock profiling connection
+ mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
+
// Wait for a bit (must at least be the delay value of the mock profiling connection) to make sure that
- // the Create the Request Counter packet gets processed by the profiling service
+ // the Periodic Counter Selection packet gets processed by the profiling service
std::this_thread::sleep_for(std::chrono::seconds(2));
- // The Connection Acknowledged Command Handler should not have updated the profiling state
+ // Check that the expected error has occurred and logged to the standard output
+ BOOST_CHECK(boost::contains(ss.str(), "Functor with requested PacketId=999 and Version=4194304 does not exist"));
+
+ // The Periodic Counter Selection Handler should not have updated the profiling state
BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
- // Check that the mock profiling connection contains one Counter Directory packet
+ // Reset the profiling service to stop any running thread
+ options.m_EnableProfiling = false;
+ profilingService.ResetExternalProfilingOptions(options, true);
+}
+
+BOOST_AUTO_TEST_CASE(CheckProfilingServiceBadPeriodicCounterSelectionPacketInvalidCounterUid)
+{
+ // Locally reduce log level to "Warning", as this test needs to parse a warning message from the standard output
+ LogLevelSwapper logLevelSwapper(armnn::LogSeverity::Warning);
+
+ // Swap the profiling connection factory in the profiling service instance with our mock one
+ SwapProfilingConnectionFactoryHelper helper;
+
+ // Reset the profiling service to the uninitialized state
+ armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
+ options.m_EnableProfiling = true;
+ ProfilingService& profilingService = ProfilingService::Instance();
+ profilingService.ResetExternalProfilingOptions(options, true);
+
+ // Bring the profiling service to the "Active" state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
+ profilingService.Update(); // Initialize the counter directory
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
+ profilingService.Update(); // Create the profiling connection
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
+ helper.ForceTransitionToState(ProfilingState::Active);
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Get the mock profiling connection
+ MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
+ BOOST_CHECK(mockProfilingConnection);
+
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
+ // external profiling service
+
+ // Periodic Counter Selection packet header:
+ // 26:31 [6] packet_family: Control Packet Family, value 0b000000
+ // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
+ // 8:15 [8] reserved: Reserved, value 0b00000000
+ // 0:7 [8] reserved: Reserved, value 0b00000000
+ uint32_t packetFamily = 0;
+ uint32_t packetId = 4;
+ uint32_t header = ((packetFamily & 0x0000003F) << 26) |
+ ((packetId & 0x000003FF) << 16);
+
+ uint32_t capturePeriod = 123456; // Some capture period (microseconds)
+
+ // Get the first valid counter UID
+ const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
+ const Counters& counters = counterDirectory.GetCounters();
+ BOOST_CHECK(counters.size() > 1);
+ uint16_t counterUidA = counters.begin()->first; // First valid counter UID
+ uint16_t counterUidB = 9999; // Second invalid counter UID
+
+ uint32_t length = 8;
+
+ auto data = std::make_unique<unsigned char[]>(length);
+ WriteUint32(data.get(), 0, capturePeriod);
+ WriteUint16(data.get(), 4, counterUidA);
+ WriteUint16(data.get(), 6, counterUidB);
+
+ // Create the Periodic Counter Selection packet
+ Packet periodicCounterSelectionPacket(header, length, data); // Length > 0, this will start the Period Counter
+ // Capture thread
+
+ // Write the packet to the mock profiling connection
+ mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
+
+ // Expecting one Periodic Counter Selection packet and at least one Periodic Counter Capture packet
+ int expectedPackets = 2;
+ std::vector<uint32_t> receivedPackets;
+
+ // Keep waiting until all the expected packets have been received
+ do
+ {
+ helper.WaitForProfilingPacketsSent();
+ const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
+ if (writtenData.empty())
+ {
+ BOOST_ERROR("Packets should be available for reading at this point");
+ return;
+ }
+ receivedPackets.insert(receivedPackets.end(), writtenData.begin(), writtenData.end());
+ expectedPackets -= boost::numeric_cast<int>(writtenData.size());
+ }
+ while (expectedPackets > 0);
+ BOOST_TEST(!receivedPackets.empty());
+
+ // The size of the expected Periodic Counter Selection packet
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 14) != receivedPackets.end()));
+ // The size of the expected Periodic Counter Capture packet
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 22) != receivedPackets.end()));
+
+ // The Periodic Counter Selection Handler should not have updated the profiling state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Reset the profiling service to stop any running thread
+ options.m_EnableProfiling = false;
+ profilingService.ResetExternalProfilingOptions(options, true);
+}
+
+BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketNoCounters)
+{
+ // Swap the profiling connection factory in the profiling service instance with our mock one
+ SwapProfilingConnectionFactoryHelper helper;
+
+ // Reset the profiling service to the uninitialized state
+ armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
+ options.m_EnableProfiling = true;
+ ProfilingService& profilingService = ProfilingService::Instance();
+ profilingService.ResetExternalProfilingOptions(options, true);
+
+ // Bring the profiling service to the "Active" state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
+ profilingService.Update(); // Initialize the counter directory
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
+ profilingService.Update(); // Create the profiling connection
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
+ helper.ForceTransitionToState(ProfilingState::Active);
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Get the mock profiling connection
+ MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
+ BOOST_CHECK(mockProfilingConnection);
+
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
+ // external profiling service
+
+ // Periodic Counter Selection packet header:
+ // 26:31 [6] packet_family: Control Packet Family, value 0b000000
+ // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
+ // 8:15 [8] reserved: Reserved, value 0b00000000
+ // 0:7 [8] reserved: Reserved, value 0b00000000
+ uint32_t packetFamily = 0;
+ uint32_t packetId = 4;
+ uint32_t header = ((packetFamily & 0x0000003F) << 26) |
+ ((packetId & 0x000003FF) << 16);
+
+ // Create the Periodic Counter Selection packet
+ Packet periodicCounterSelectionPacket(header); // Length == 0, this will disable the collection of counters
+
+ // Write the packet to the mock profiling connection
+ mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
+
+ // Wait for the Periodic Counter Selection packet to be sent
+ helper.WaitForProfilingPacketsSent();
+
+ // The Periodic Counter Selection Handler should not have updated the profiling state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Check that the mock profiling connection contains one Periodic Counter Selection
const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
- BOOST_TEST(writtenData.size() == 1);
- BOOST_TEST(writtenData[0] == 416); // The size of a valid Counter Directory packet
+ BOOST_TEST(writtenData.size() == 1); // Only one packet is expected (no Periodic Counter packets)
+ BOOST_TEST(writtenData[0] == 12); // The size of the expected Periodic Counter Selection (echos the sent one)
+
+ // Reset the profiling service to stop any running thread
+ options.m_EnableProfiling = false;
+ profilingService.ResetExternalProfilingOptions(options, true);
+}
+
+BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketSingleCounter)
+{
+ // Swap the profiling connection factory in the profiling service instance with our mock one
+ SwapProfilingConnectionFactoryHelper helper;
+
+ // Reset the profiling service to the uninitialized state
+ armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
+ options.m_EnableProfiling = true;
+ ProfilingService& profilingService = ProfilingService::Instance();
+ profilingService.ResetExternalProfilingOptions(options, true);
+
+ // Bring the profiling service to the "Active" state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
+ profilingService.Update(); // Initialize the counter directory
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
+ profilingService.Update(); // Create the profiling connection
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
+ helper.ForceTransitionToState(ProfilingState::Active);
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Get the mock profiling connection
+ MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
+ BOOST_CHECK(mockProfilingConnection);
+
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
+ // external profiling service
+
+ // Periodic Counter Selection packet header:
+ // 26:31 [6] packet_family: Control Packet Family, value 0b000000
+ // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
+ // 8:15 [8] reserved: Reserved, value 0b00000000
+ // 0:7 [8] reserved: Reserved, value 0b00000000
+ uint32_t packetFamily = 0;
+ uint32_t packetId = 4;
+ uint32_t header = ((packetFamily & 0x0000003F) << 26) |
+ ((packetId & 0x000003FF) << 16);
+
+ uint32_t capturePeriod = 123456; // Some capture period (microseconds)
+
+ // Get the first valid counter UID
+ const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
+ const Counters& counters = counterDirectory.GetCounters();
+ BOOST_CHECK(!counters.empty());
+ uint16_t counterUid = counters.begin()->first; // Valid counter UID
+
+ uint32_t length = 6;
+
+ auto data = std::make_unique<unsigned char[]>(length);
+ WriteUint32(data.get(), 0, capturePeriod);
+ WriteUint16(data.get(), 4, counterUid);
+
+ // Create the Periodic Counter Selection packet
+ Packet periodicCounterSelectionPacket(header, length, data); // Length > 0, this will start the Period Counter
+ // Capture thread
+
+ // Write the packet to the mock profiling connection
+ mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
+
+ // Expecting one Periodic Counter Selection packet and at least one Periodic Counter Capture packet
+ int expectedPackets = 2;
+ std::vector<uint32_t> receivedPackets;
+
+ // Keep waiting until all the expected packets have been received
+ do
+ {
+ helper.WaitForProfilingPacketsSent();
+ const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
+ if (writtenData.empty())
+ {
+ BOOST_ERROR("Packets should be available for reading at this point");
+ return;
+ }
+ receivedPackets.insert(receivedPackets.end(), writtenData.begin(), writtenData.end());
+ expectedPackets -= boost::numeric_cast<int>(writtenData.size());
+ }
+ while (expectedPackets > 0);
+ BOOST_TEST(!receivedPackets.empty());
+
+ // The size of the expected Periodic Counter Selection packet (echos the sent one)
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 14) != receivedPackets.end()));
+ // The size of the expected Periodic Counter Capture packet
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 22) != receivedPackets.end()));
+
+ // The Periodic Counter Selection Handler should not have updated the profiling state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Reset the profiling service to stop any running thread
+ options.m_EnableProfiling = false;
+ profilingService.ResetExternalProfilingOptions(options, true);
+}
+
+BOOST_AUTO_TEST_CASE(CheckProfilingServiceGoodPeriodicCounterSelectionPacketMultipleCounters)
+{
+ // Swap the profiling connection factory in the profiling service instance with our mock one
+ SwapProfilingConnectionFactoryHelper helper;
+
+ // Reset the profiling service to the uninitialized state
+ armnn::Runtime::CreationOptions::ExternalProfilingOptions options;
+ options.m_EnableProfiling = true;
+ ProfilingService& profilingService = ProfilingService::Instance();
+ profilingService.ResetExternalProfilingOptions(options, true);
+
+ // Bring the profiling service to the "Active" state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Uninitialised);
+ profilingService.Update(); // Initialize the counter directory
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::NotConnected);
+ profilingService.Update(); // Create the profiling connection
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::WaitingForAck);
+ profilingService.Update(); // Start the command handler and the send thread
+
+ // Wait for the Stream Metadata packet the be sent
+ // (we are not testing the connection acknowledgement here so it will be ignored by this test)
+ helper.WaitForProfilingPacketsSent();
+
+ // Force the profiling service to the "Active" state
+ helper.ForceTransitionToState(ProfilingState::Active);
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
+
+ // Get the mock profiling connection
+ MockProfilingConnection* mockProfilingConnection = helper.GetMockProfilingConnection();
+ BOOST_CHECK(mockProfilingConnection);
+
+ // Remove the packets received so far
+ mockProfilingConnection->Clear();
+
+ // Write a "Periodic Counter Selection" packet into the mock profiling connection, to simulate an input from an
+ // external profiling service
+
+ // Periodic Counter Selection packet header:
+ // 26:31 [6] packet_family: Control Packet Family, value 0b000000
+ // 16:25 [10] packet_id: Packet identifier, value 0b0000000100
+ // 8:15 [8] reserved: Reserved, value 0b00000000
+ // 0:7 [8] reserved: Reserved, value 0b00000000
+ uint32_t packetFamily = 0;
+ uint32_t packetId = 4;
+ uint32_t header = ((packetFamily & 0x0000003F) << 26) |
+ ((packetId & 0x000003FF) << 16);
+
+ uint32_t capturePeriod = 123456; // Some capture period (microseconds)
+
+ // Get the first valid counter UID
+ const ICounterDirectory& counterDirectory = profilingService.GetCounterDirectory();
+ const Counters& counters = counterDirectory.GetCounters();
+ BOOST_CHECK(counters.size() > 1);
+ uint16_t counterUidA = counters.begin()->first; // First valid counter UID
+ uint16_t counterUidB = (counters.begin()++)->first; // Second valid counter UID
+
+ uint32_t length = 8;
+
+ auto data = std::make_unique<unsigned char[]>(length);
+ WriteUint32(data.get(), 0, capturePeriod);
+ WriteUint16(data.get(), 4, counterUidA);
+ WriteUint16(data.get(), 6, counterUidB);
+
+ // Create the Periodic Counter Selection packet
+ Packet periodicCounterSelectionPacket(header, length, data); // Length > 0, this will start the Period Counter
+ // Capture thread
+
+ // Write the packet to the mock profiling connection
+ mockProfilingConnection->WritePacket(std::move(periodicCounterSelectionPacket));
+
+ // Expecting one Periodic Counter Selection packet and at least one Periodic Counter Capture packet
+ int expectedPackets = 2;
+ std::vector<uint32_t> receivedPackets;
+
+ // Keep waiting until all the expected packets have been received
+ do
+ {
+ helper.WaitForProfilingPacketsSent();
+ const std::vector<uint32_t> writtenData = mockProfilingConnection->GetWrittenData();
+ if (writtenData.empty())
+ {
+ BOOST_ERROR("Packets should be available for reading at this point");
+ return;
+ }
+ receivedPackets.insert(receivedPackets.end(), writtenData.begin(), writtenData.end());
+ expectedPackets -= boost::numeric_cast<int>(writtenData.size());
+ }
+ while (expectedPackets > 0);
+ BOOST_TEST(!receivedPackets.empty());
+
+ // The size of the expected Periodic Counter Selection packet (echos the sent one)
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 16) != receivedPackets.end()));
+ // The size of the expected Periodic Counter Capture packet
+ BOOST_TEST((std::find(receivedPackets.begin(), receivedPackets.end(), 28) != receivedPackets.end()));
+
+ // The Periodic Counter Selection Handler should not have updated the profiling state
+ BOOST_CHECK(profilingService.GetCurrentState() == ProfilingState::Active);
// Reset the profiling service to stop any running thread
options.m_EnableProfiling = false;