ArmNN
 21.02
SendCounterPacketTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "ProfilingMocks.hpp"
7 #include "ProfilingTestUtils.hpp"
9 
10 #include <BufferManager.hpp>
11 #include <CounterDirectory.hpp>
12 #include <common/include/EncodeVersion.hpp>
13 #include <ProfilingUtils.hpp>
14 #include <SendCounterPacket.hpp>
15 #include <Processes.hpp>
16 
17 #include <armnn/Exceptions.hpp>
18 #include <armnn/Conversion.hpp>
19 #include <armnn/Utils.hpp>
20 
21 #include <common/include/Constants.hpp>
22 
23 #include <boost/test/unit_test.hpp>
24 
25 #include <chrono>
26 
27 using namespace armnn::profiling;
28 
29 namespace
30 {
31 
32 // A short delay to wait for the thread to process a packet.
33 uint16_t constexpr WAIT_UNTIL_READABLE_MS = 20;
34 
35 void SetNotConnectedProfilingState(ProfilingStateMachine& profilingStateMachine)
36 {
37  ProfilingState currentState = profilingStateMachine.GetCurrentState();
38  switch (currentState)
39  {
41  profilingStateMachine.TransitionToState(ProfilingState::Active);
46  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
49  return;
50  default:
51  BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
52  }
53 }
54 
55 void SetWaitingForAckProfilingState(ProfilingStateMachine& profilingStateMachine)
56 {
57  ProfilingState currentState = profilingStateMachine.GetCurrentState();
58  switch (currentState)
59  {
63  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
66  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
69  return;
70  default:
71  BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
72  }
73 }
74 
75 void SetActiveProfilingState(ProfilingStateMachine& profilingStateMachine)
76 {
77  ProfilingState currentState = profilingStateMachine.GetCurrentState();
78  switch (currentState)
79  {
81  profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
84  profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
87  profilingStateMachine.TransitionToState(ProfilingState::Active);
90  return;
91  default:
92  BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
93  }
94 }
95 
96 } // Anonymous namespace
97 
98 BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
99 
101 
102 BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
103 {
104  MockBufferManager mockBuffer(512);
105  MockSendCounterPacket mockSendCounterPacket(mockBuffer);
106 
107  mockSendCounterPacket.SendStreamMetaDataPacket();
108 
109  auto packetBuffer = mockBuffer.GetReadableBuffer();
110  const char* buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
111 
112  BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
113 
114  mockBuffer.MarkRead(packetBuffer);
115 
116  CounterDirectory counterDirectory;
117  mockSendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
118 
119  packetBuffer = mockBuffer.GetReadableBuffer();
120  buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
121 
122  BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
123 
124  mockBuffer.MarkRead(packetBuffer);
125 
126  uint64_t timestamp = 0;
127  std::vector<CounterValue> indexValuePairs;
128 
129  mockSendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
130 
131  packetBuffer = mockBuffer.GetReadableBuffer();
132  buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
133 
134  BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
135 
136  mockBuffer.MarkRead(packetBuffer);
137 
138  uint32_t capturePeriod = 0;
139  std::vector<uint16_t> selectedCounterIds;
140  mockSendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
141 
142  packetBuffer = mockBuffer.GetReadableBuffer();
143  buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
144 
145  BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
146 
147  mockBuffer.MarkRead(packetBuffer);
148 }
149 
150 BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest)
151 {
152  // Error no space left in buffer
153  MockBufferManager mockBuffer1(10);
154  SendCounterPacket sendPacket1(mockBuffer1);
155 
156  uint32_t capturePeriod = 1000;
157  std::vector<uint16_t> selectedCounterIds;
158  BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
160 
161  // Packet without any counters
162  MockBufferManager mockBuffer2(512);
163  SendCounterPacket sendPacket2(mockBuffer2);
164 
165  sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
166  auto readBuffer2 = mockBuffer2.GetReadableBuffer();
167 
168  uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
169  uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
170  uint32_t period = ReadUint32(readBuffer2, 8);
171 
172  BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
173  BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
174  BOOST_TEST(headerWord1 == 4); // data lenght
175  BOOST_TEST(period == 1000); // capture period
176 
177  // Full packet message
178  MockBufferManager mockBuffer3(512);
179  SendCounterPacket sendPacket3(mockBuffer3);
180 
181  selectedCounterIds.reserve(5);
182  selectedCounterIds.emplace_back(100);
183  selectedCounterIds.emplace_back(200);
184  selectedCounterIds.emplace_back(300);
185  selectedCounterIds.emplace_back(400);
186  selectedCounterIds.emplace_back(500);
187  sendPacket3.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
188  auto readBuffer3 = mockBuffer3.GetReadableBuffer();
189 
190  headerWord0 = ReadUint32(readBuffer3, 0);
191  headerWord1 = ReadUint32(readBuffer3, 4);
192  period = ReadUint32(readBuffer3, 8);
193 
194  BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
195  BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
196  BOOST_TEST(headerWord1 == 14); // data lenght
197  BOOST_TEST(period == 1000); // capture period
198 
199  uint16_t counterId = 0;
200  uint32_t offset = 12;
201 
202  // Counter Ids
203  for(const uint16_t& id : selectedCounterIds)
204  {
205  counterId = ReadUint16(readBuffer3, offset);
206  BOOST_TEST(counterId == id);
207  offset += 2;
208  }
209 }
210 
211 BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest)
212 {
213  ProfilingStateMachine profilingStateMachine;
214 
215  // Error no space left in buffer
216  MockBufferManager mockBuffer1(10);
217  SendCounterPacket sendPacket1(mockBuffer1);
218 
219  auto captureTimestamp = std::chrono::steady_clock::now();
220  uint64_t time = static_cast<uint64_t >(captureTimestamp.time_since_epoch().count());
221  std::vector<CounterValue> indexValuePairs;
222 
223  BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterCapturePacket(time, indexValuePairs),
225 
226  // Packet without any counters
227  MockBufferManager mockBuffer2(512);
228  SendCounterPacket sendPacket2(mockBuffer2);
229 
230  sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs);
231  auto readBuffer2 = mockBuffer2.GetReadableBuffer();
232 
233  uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
234  uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
235  uint64_t readTimestamp = ReadUint64(readBuffer2, 8);
236 
237  BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
238  BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
239  BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
240  BOOST_TEST(headerWord1 == 8); // data length
241  BOOST_TEST(time == readTimestamp); // capture period
242 
243  // Full packet message
244  MockBufferManager mockBuffer3(512);
245  SendCounterPacket sendPacket3(mockBuffer3);
246 
247  indexValuePairs.reserve(5);
248  indexValuePairs.emplace_back(CounterValue{0, 100});
249  indexValuePairs.emplace_back(CounterValue{1, 200});
250  indexValuePairs.emplace_back(CounterValue{2, 300});
251  indexValuePairs.emplace_back(CounterValue{3, 400});
252  indexValuePairs.emplace_back(CounterValue{4, 500});
253  sendPacket3.SendPeriodicCounterCapturePacket(time, indexValuePairs);
254  auto readBuffer3 = mockBuffer3.GetReadableBuffer();
255 
256  headerWord0 = ReadUint32(readBuffer3, 0);
257  headerWord1 = ReadUint32(readBuffer3, 4);
258  uint64_t readTimestamp2 = ReadUint64(readBuffer3, 8);
259 
260  BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
261  BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
262  BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
263  BOOST_TEST(headerWord1 == 38); // data length
264  BOOST_TEST(time == readTimestamp2); // capture period
265 
266  uint16_t counterIndex = 0;
267  uint32_t counterValue = 100;
268  uint32_t offset = 16;
269 
270  // Counter Ids
271  for (auto it = indexValuePairs.begin(), end = indexValuePairs.end(); it != end; ++it)
272  {
273  // Check Counter Index
274  uint16_t readIndex = ReadUint16(readBuffer3, offset);
275  BOOST_TEST(counterIndex == readIndex);
276  counterIndex++;
277  offset += 2;
278 
279  // Check Counter Value
280  uint32_t readValue = ReadUint32(readBuffer3, offset);
281  BOOST_TEST(counterValue == readValue);
282  counterValue += 100;
283  offset += 4;
284  }
285 
286 }
287 
288 BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
289 {
290  uint32_t sizeUint32 = armnn::numeric_cast<uint32_t>(sizeof(uint32_t));
291 
292  // Error no space left in buffer
293  MockBufferManager mockBuffer1(10);
294  SendCounterPacket sendPacket1(mockBuffer1);
295  BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion);
296 
297  // Full metadata packet
298 
299  std::string processName = GetProcessName().substr(0, 60);
300 
301  uint32_t infoSize = armnn::numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1;
302  uint32_t hardwareVersionSize = armnn::numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1;
303  uint32_t softwareVersionSize = armnn::numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1;
304  uint32_t processNameSize = armnn::numeric_cast<uint32_t>(processName.size()) + 1;
305 
306  // Supported Packets
307  // Packet Encoding version 1.0.0
308  // Control packet family
309  // Stream metadata packet (packet family=0; packet id=0)
310  // Connection Acknowledged packet ( packet family=0, packet id=1) Version 1.0.0
311  // Counter Directory packet (packet family=0; packet id=2) Version 1.0.0
312  // Request Counter Directory packet ( packet family=0, packet id=3) Version 1.0.0
313  // Periodic Counter Selection packet ( packet family=0, packet id=4) Version 1.0.0
314  // Per Job Counter Selection packet ( packet family=0, packet id=5) Version 1.0.0
315  // Activate Timeline Reporting (packet family = 0, packet id = 6) Version 1.0.0
316  // Deactivate Timeline Reporting (packet family = 0, packet id = 7) Version 1.0.0
317  // Counter Packet Family
318  // Periodic Counter Capture (packet_family = 3, packet_class = 0, packet_type = 0) Version 1.0.0
319  // Per-Job Counter Capture (packet_family = 3, packet_class = 1, packet_type = 0,1) Version 1.0.0
320  // Timeline Packet Family
321  // Timeline Message Directory (packet_family = 1, packet_class = 0, packet_type = 0) Version 1.0.0
322  // Timeline Message (packet_family = 1, packet_class = 0, packet_type = 1) Version 1.0.0
323  std::vector<std::pair<uint32_t, uint32_t>> packetVersions;
324  packetVersions.push_back(std::make_pair(ConstructHeader(0, 0), arm::pipe::EncodeVersion(1, 0, 0)));
325  packetVersions.push_back(std::make_pair(ConstructHeader(0, 1), arm::pipe::EncodeVersion(1, 0, 0)));
326  packetVersions.push_back(std::make_pair(ConstructHeader(0, 2), arm::pipe::EncodeVersion(1, 0, 0)));
327  packetVersions.push_back(std::make_pair(ConstructHeader(0, 3), arm::pipe::EncodeVersion(1, 0, 0)));
328  packetVersions.push_back(std::make_pair(ConstructHeader(0, 4), arm::pipe::EncodeVersion(1, 0, 0)));
329  packetVersions.push_back(std::make_pair(ConstructHeader(0, 5), arm::pipe::EncodeVersion(1, 0, 0)));
330  packetVersions.push_back(std::make_pair(ConstructHeader(0, 6), arm::pipe::EncodeVersion(1, 0, 0)));
331  packetVersions.push_back(std::make_pair(ConstructHeader(0, 7), arm::pipe::EncodeVersion(1, 0, 0)));
332  packetVersions.push_back(std::make_pair(ConstructHeader(3, 0, 0), arm::pipe::EncodeVersion(1, 0, 0)));
333  packetVersions.push_back(std::make_pair(ConstructHeader(3, 1, 0), arm::pipe::EncodeVersion(1, 0, 0)));
334  packetVersions.push_back(std::make_pair(ConstructHeader(3, 1, 1), arm::pipe::EncodeVersion(1, 0, 0)));
335  packetVersions.push_back(std::make_pair(ConstructHeader(1, 0, 0), arm::pipe::EncodeVersion(1, 0, 0)));
336  packetVersions.push_back(std::make_pair(ConstructHeader(1, 0, 1), arm::pipe::EncodeVersion(1, 0, 0)));
337 
338  uint32_t packetEntries = static_cast<uint32_t>(packetVersions.size());
339 
340  MockBufferManager mockBuffer2(512);
341  SendCounterPacket sendPacket2(mockBuffer2);
342  sendPacket2.SendStreamMetaDataPacket();
343  auto readBuffer2 = mockBuffer2.GetReadableBuffer();
344 
345  uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
346  uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32);
347 
348  BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
349  BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id
350 
351  uint32_t totalLength = armnn::numeric_cast<uint32_t>(2 * sizeUint32 +
352  10 * sizeUint32 + infoSize +
353  hardwareVersionSize + softwareVersionSize +
354  processNameSize + sizeUint32 +
355  2 * packetEntries * sizeUint32);
356 
357  BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length
358 
359  uint32_t offset = sizeUint32 * 2;
360  BOOST_TEST(ReadUint32(readBuffer2, offset) == arm::pipe::PIPE_MAGIC); // pipe_magic
361  offset += sizeUint32;
362  BOOST_TEST(ReadUint32(readBuffer2, offset) == arm::pipe::EncodeVersion(1, 0, 0)); // stream_metadata_version
363  offset += sizeUint32;
364  BOOST_TEST(ReadUint32(readBuffer2, offset) == MAX_METADATA_PACKET_LENGTH); // max_data_len
365  offset += sizeUint32;
367  BOOST_TEST(ReadUint32(readBuffer2, offset) == armnn::numeric_cast<uint32_t>(pid));
368  offset += sizeUint32;
369  uint32_t poolOffset = 10 * sizeUint32;
370  BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_info
371  offset += sizeUint32;
372  poolOffset += infoSize;
373  BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_hw_version
374  offset += sizeUint32;
375  poolOffset += hardwareVersionSize;
376  BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_sw_version
377  offset += sizeUint32;
378  poolOffset += softwareVersionSize;
379  BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_process_name
380  offset += sizeUint32;
381  poolOffset += processNameSize;
382  BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_packet_version_table
383  offset += sizeUint32;
384  BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved
385 
386  const unsigned char* readData2 = readBuffer2->GetReadableData();
387 
388  offset += sizeUint32;
389  if (infoSize)
390  {
391  BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareInfo().c_str()) == 0);
392  offset += infoSize;
393  }
394 
395  if (hardwareVersionSize)
396  {
397  BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetHardwareVersion().c_str()) == 0);
398  offset += hardwareVersionSize;
399  }
400 
401  if (softwareVersionSize)
402  {
403  BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareVersion().c_str()) == 0);
404  offset += softwareVersionSize;
405  }
406 
407  if (processNameSize)
408  {
409  BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetProcessName().c_str()) == 0);
410  offset += processNameSize;
411  }
412 
413  if (packetEntries)
414  {
415  uint32_t numberOfEntries = ReadUint32(readBuffer2, offset);
416  BOOST_TEST((numberOfEntries >> 16) == packetEntries);
417  offset += sizeUint32;
418  for (std::pair<uint32_t, uint32_t>& packetVersion : packetVersions)
419  {
420  uint32_t readPacketId = ReadUint32(readBuffer2, offset);
421  BOOST_TEST(packetVersion.first == readPacketId);
422  offset += sizeUint32;
423  uint32_t readVersion = ReadUint32(readBuffer2, offset);
424  BOOST_TEST(packetVersion.second == readVersion);
425  offset += sizeUint32;
426  }
427  }
428 
429  BOOST_TEST(offset == totalLength);
430 }
431 
432 BOOST_AUTO_TEST_CASE(CreateDeviceRecordTest)
433 {
434  MockBufferManager mockBuffer(0);
435  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
436 
437  // Create a device for testing
438  uint16_t deviceUid = 27;
439  const std::string deviceName = "some_device";
440  uint16_t deviceCores = 3;
441  const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
442 
443  // Create a device record
444  SendCounterPacket::DeviceRecord deviceRecord;
445  std::string errorMessage;
446  bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
447 
448  BOOST_CHECK(result);
449  BOOST_CHECK(errorMessage.empty());
450  BOOST_CHECK(deviceRecord.size() == 6); // Size in words: header [2] + device name [4]
451 
452  uint16_t deviceRecordWord0[]
453  {
454  static_cast<uint16_t>(deviceRecord[0] >> 16),
455  static_cast<uint16_t>(deviceRecord[0])
456  };
457  BOOST_CHECK(deviceRecordWord0[0] == deviceUid); // uid
458  BOOST_CHECK(deviceRecordWord0[1] == deviceCores); // cores
459  BOOST_CHECK(deviceRecord[1] == 8); // name_offset
460  BOOST_CHECK(deviceRecord[2] == deviceName.size() + 1); // The length of the SWTrace string (name)
461  BOOST_CHECK(std::memcmp(deviceRecord.data() + 3, deviceName.data(), deviceName.size()) == 0); // name
462 }
463 
464 BOOST_AUTO_TEST_CASE(CreateInvalidDeviceRecordTest)
465 {
466  MockBufferManager mockBuffer(0);
467  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
468 
469  // Create a device for testing
470  uint16_t deviceUid = 27;
471  const std::string deviceName = "some€£invalid‡device";
472  uint16_t deviceCores = 3;
473  const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
474 
475  // Create a device record
476  SendCounterPacket::DeviceRecord deviceRecord;
477  std::string errorMessage;
478  bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
479 
480  BOOST_CHECK(!result);
481  BOOST_CHECK(!errorMessage.empty());
482  BOOST_CHECK(deviceRecord.empty());
483 }
484 
485 BOOST_AUTO_TEST_CASE(CreateCounterSetRecordTest)
486 {
487  MockBufferManager mockBuffer(0);
488  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
489 
490  // Create a counter set for testing
491  uint16_t counterSetUid = 27;
492  const std::string counterSetName = "some_counter_set";
493  uint16_t counterSetCount = 3421;
494  const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
495 
496  // Create a counter set record
497  SendCounterPacket::CounterSetRecord counterSetRecord;
498  std::string errorMessage;
499  bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
500 
501  BOOST_CHECK(result);
502  BOOST_CHECK(errorMessage.empty());
503  BOOST_CHECK(counterSetRecord.size() == 8); // Size in words: header [2] + counter set name [6]
504 
505  uint16_t counterSetRecordWord0[]
506  {
507  static_cast<uint16_t>(counterSetRecord[0] >> 16),
508  static_cast<uint16_t>(counterSetRecord[0])
509  };
510  BOOST_CHECK(counterSetRecordWord0[0] == counterSetUid); // uid
511  BOOST_CHECK(counterSetRecordWord0[1] == counterSetCount); // cores
512  BOOST_CHECK(counterSetRecord[1] == 8); // name_offset
513  BOOST_CHECK(counterSetRecord[2] == counterSetName.size() + 1); // The length of the SWTrace string (name)
514  BOOST_CHECK(std::memcmp(counterSetRecord.data() + 3, counterSetName.data(), counterSetName.size()) == 0); // name
515 }
516 
517 BOOST_AUTO_TEST_CASE(CreateInvalidCounterSetRecordTest)
518 {
519  MockBufferManager mockBuffer(0);
520  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
521 
522  // Create a counter set for testing
523  uint16_t counterSetUid = 27;
524  const std::string counterSetName = "some invalid_counter€£set";
525  uint16_t counterSetCount = 3421;
526  const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
527 
528  // Create a counter set record
529  SendCounterPacket::CounterSetRecord counterSetRecord;
530  std::string errorMessage;
531  bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
532 
533  BOOST_CHECK(!result);
534  BOOST_CHECK(!errorMessage.empty());
535  BOOST_CHECK(counterSetRecord.empty());
536 }
537 
538 BOOST_AUTO_TEST_CASE(CreateEventRecordTest)
539 {
540  MockBufferManager mockBuffer(0);
541  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
542 
543  // Create a counter for testing
544  uint16_t counterUid = 7256;
545  uint16_t maxCounterUid = 132;
546  uint16_t deviceUid = 132;
547  uint16_t counterSetUid = 4497;
548  uint16_t counterClass = 1;
549  uint16_t counterInterpolation = 1;
550  double counterMultiplier = 1234.567f;
551  const std::string counterName = "some_valid_counter";
552  const std::string counterDescription = "a_counter_for_testing";
553  const std::string counterUnits = "Mrads2";
554  const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
555  counterUid,
556  maxCounterUid,
557  counterClass,
558  counterInterpolation,
559  counterMultiplier,
560  counterName,
561  counterDescription,
562  counterUnits,
563  deviceUid,
564  counterSetUid);
565  ARMNN_ASSERT(counter);
566 
567  // Create an event record
568  SendCounterPacket::EventRecord eventRecord;
569  std::string errorMessage;
570  bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
571 
572  BOOST_CHECK(result);
573  BOOST_CHECK(errorMessage.empty());
574  BOOST_CHECK(eventRecord.size() == 24); // Size in words: header [8] + counter name [6] + description [7] + units [3]
575 
576  uint16_t eventRecordWord0[]
577  {
578  static_cast<uint16_t>(eventRecord[0] >> 16),
579  static_cast<uint16_t>(eventRecord[0])
580  };
581  uint16_t eventRecordWord1[]
582  {
583  static_cast<uint16_t>(eventRecord[1] >> 16),
584  static_cast<uint16_t>(eventRecord[1])
585  };
586  uint16_t eventRecordWord2[]
587  {
588  static_cast<uint16_t>(eventRecord[2] >> 16),
589  static_cast<uint16_t>(eventRecord[2])
590  };
591  uint32_t eventRecordWord34[]
592  {
593  eventRecord[3],
594  eventRecord[4]
595  };
596 
597  BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
598  BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
599  BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
600 
601  BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
602  BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
603  BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
604  BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
605 
607  uint32_t eventRecordBlockSize = 8u * sizeof(uint32_t);
608  uint32_t counterNameOffset = eventRecordBlockSize; // The name is the first item in pool
609  uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
610  4u + // Counter name length (uint32_t)
611  counterName.size() + // 18u
612  1u + // Null-terminator
613  1u; // Rounding to the next word
614 
615  size_t counterUnitsOffset = counterDescriptionOffset + // Counter description offset
616  4u + // Counter description length (uint32_t)
617  counterDescription.size() + // 21u
618  1u + // Null-terminator
619  2u; // Rounding to the next word
620 
622 
623  BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
624  BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
625  BOOST_CHECK(eventRecord[7] == counterUnitsOffset); // units_offset
626 
627  // Offsets are relative to the start of the eventRecord
628  auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data());
629  size_t uint32_t_size = sizeof(uint32_t);
630 
631  // The length of the SWTrace string (name)
632  BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
633  // The counter name
634  BOOST_CHECK(std::memcmp(eventRecordPool +
635  counterNameOffset + // Offset
636  uint32_t_size /* The length of the name */,
637  counterName.data(),
638  counterName.size()) == 0); // name
639  // The null-terminator at the end of the name
640  BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
641 
642  // The length of the SWTrace string (description)
643  BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
644  // The counter description
645  BOOST_CHECK(std::memcmp(eventRecordPool +
646  counterDescriptionOffset + // Offset
647  uint32_t_size /* The length of the description */,
648  counterDescription.data(),
649  counterDescription.size()) == 0); // description
650  // The null-terminator at the end of the description
651  BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
652 
653  // The length of the SWTrace namestring (units)
654  BOOST_CHECK(eventRecordPool[counterUnitsOffset] == counterUnits.size() + 1);
655  // The counter units
656  BOOST_CHECK(std::memcmp(eventRecordPool +
657  counterUnitsOffset + // Offset
658  uint32_t_size /* The length of the units */,
659  counterUnits.data(),
660  counterUnits.size()) == 0); // units
661  // The null-terminator at the end of the units
662  BOOST_CHECK(eventRecordPool[counterUnitsOffset + uint32_t_size + counterUnits.size()] == '\0');
663 }
664 
665 BOOST_AUTO_TEST_CASE(CreateEventRecordNoUnitsTest)
666 {
667  MockBufferManager mockBuffer(0);
668  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
669 
670  // Create a counter for testing
671  uint16_t counterUid = 44312;
672  uint16_t maxCounterUid = 345;
673  uint16_t deviceUid = 101;
674  uint16_t counterSetUid = 34035;
675  uint16_t counterClass = 0;
676  uint16_t counterInterpolation = 1;
677  double counterMultiplier = 4435.0023f;
678  const std::string counterName = "some_valid_counter";
679  const std::string counterDescription = "a_counter_for_testing";
680  const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
681  counterUid,
682  maxCounterUid,
683  counterClass,
684  counterInterpolation,
685  counterMultiplier,
686  counterName,
687  counterDescription,
688  "",
689  deviceUid,
690  counterSetUid);
691  ARMNN_ASSERT(counter);
692 
693  // Create an event record
694  SendCounterPacket::EventRecord eventRecord;
695  std::string errorMessage;
696  bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
697 
698  BOOST_CHECK(result);
699  BOOST_CHECK(errorMessage.empty());
700  BOOST_CHECK(eventRecord.size() == 21); // Size in words: header [8] + counter name [6] + description [7]
701 
702  uint16_t eventRecordWord0[]
703  {
704  static_cast<uint16_t>(eventRecord[0] >> 16),
705  static_cast<uint16_t>(eventRecord[0])
706  };
707  uint16_t eventRecordWord1[]
708  {
709  static_cast<uint16_t>(eventRecord[1] >> 16),
710  static_cast<uint16_t>(eventRecord[1])
711  };
712  uint16_t eventRecordWord2[]
713  {
714  static_cast<uint16_t>(eventRecord[2] >> 16),
715  static_cast<uint16_t>(eventRecord[2])
716  };
717  uint32_t eventRecordWord34[]
718  {
719  eventRecord[3],
720  eventRecord[4]
721  };
722  BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
723  BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
724  BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
725  BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
726  BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
727  BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
728  BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
729 
731  uint32_t eventRecordBlockSize = 8u * sizeof(uint32_t);
732  uint32_t counterNameOffset = eventRecordBlockSize; // The name is the first item in pool
733  uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
734  4u + // Counter name length (uint32_t)
735  counterName.size() + // 18u
736  1u + // Null-terminator
737  1u; // Rounding to the next word
739 
740  BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
741  BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
742  BOOST_CHECK(eventRecord[7] == 0); // units_offset
743 
744  // Offsets are relative to the start of the eventRecord
745  auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data());
746  size_t uint32_t_size = sizeof(uint32_t);
747 
748  // The length of the SWTrace string (name)
749  BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
750  // The counter name
751  BOOST_CHECK(std::memcmp(eventRecordPool +
752  counterNameOffset + // Offset
753  uint32_t_size, // The length of the name
754  counterName.data(),
755  counterName.size()) == 0); // name
756  // The null-terminator at the end of the name
757  BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
758 
759  // The length of the SWTrace string (description)
760  BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
761  // The counter description
762  BOOST_CHECK(std::memcmp(eventRecordPool +
763  counterDescriptionOffset + // Offset
764  uint32_t_size, // The length of the description
765  counterDescription.data(),
766  counterDescription.size()) == 0); // description
767  // The null-terminator at the end of the description
768  BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
769 }
770 
771 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest1)
772 {
773  MockBufferManager mockBuffer(0);
774  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
775 
776  // Create a counter for testing
777  uint16_t counterUid = 7256;
778  uint16_t maxCounterUid = 132;
779  uint16_t deviceUid = 132;
780  uint16_t counterSetUid = 4497;
781  uint16_t counterClass = 1;
782  uint16_t counterInterpolation = 1;
783  double counterMultiplier = 1234.567f;
784  const std::string counterName = "some_invalid_counter £££"; // Invalid name
785  const std::string counterDescription = "a_counter_for_testing";
786  const std::string counterUnits = "Mrads2";
787  const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
788  counterUid,
789  maxCounterUid,
790  counterClass,
791  counterInterpolation,
792  counterMultiplier,
793  counterName,
794  counterDescription,
795  counterUnits,
796  deviceUid,
797  counterSetUid);
798  ARMNN_ASSERT(counter);
799 
800  // Create an event record
801  SendCounterPacket::EventRecord eventRecord;
802  std::string errorMessage;
803  bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
804 
805  BOOST_CHECK(!result);
806  BOOST_CHECK(!errorMessage.empty());
807  BOOST_CHECK(eventRecord.empty());
808 }
809 
810 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest2)
811 {
812  MockBufferManager mockBuffer(0);
813  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
814 
815  // Create a counter for testing
816  uint16_t counterUid = 7256;
817  uint16_t maxCounterUid = 132;
818  uint16_t deviceUid = 132;
819  uint16_t counterSetUid = 4497;
820  uint16_t counterClass = 1;
821  uint16_t counterInterpolation = 1;
822  double counterMultiplier = 1234.567f;
823  const std::string counterName = "some_invalid_counter";
824  const std::string counterDescription = "an invalid d€scription"; // Invalid description
825  const std::string counterUnits = "Mrads2";
826  const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
827  counterUid,
828  maxCounterUid,
829  counterClass,
830  counterInterpolation,
831  counterMultiplier,
832  counterName,
833  counterDescription,
834  counterUnits,
835  deviceUid,
836  counterSetUid);
837  ARMNN_ASSERT(counter);
838 
839  // Create an event record
840  SendCounterPacket::EventRecord eventRecord;
841  std::string errorMessage;
842  bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
843 
844  BOOST_CHECK(!result);
845  BOOST_CHECK(!errorMessage.empty());
846  BOOST_CHECK(eventRecord.empty());
847 }
848 
849 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest3)
850 {
851  MockBufferManager mockBuffer(0);
852  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
853 
854  // Create a counter for testing
855  uint16_t counterUid = 7256;
856  uint16_t maxCounterUid = 132;
857  uint16_t deviceUid = 132;
858  uint16_t counterSetUid = 4497;
859  uint16_t counterClass = 1;
860  uint16_t counterInterpolation = 1;
861  double counterMultiplier = 1234.567f;
862  const std::string counterName = "some_invalid_counter";
863  const std::string counterDescription = "a valid description";
864  const std::string counterUnits = "Mrad s2"; // Invalid units
865  const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
866  counterUid,
867  maxCounterUid,
868  counterClass,
869  counterInterpolation,
870  counterMultiplier,
871  counterName,
872  counterDescription,
873  counterUnits,
874  deviceUid,
875  counterSetUid);
876  ARMNN_ASSERT(counter);
877 
878  // Create an event record
879  SendCounterPacket::EventRecord eventRecord;
880  std::string errorMessage;
881  bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
882 
883  BOOST_CHECK(!result);
884  BOOST_CHECK(!errorMessage.empty());
885  BOOST_CHECK(eventRecord.empty());
886 }
887 
888 BOOST_AUTO_TEST_CASE(CreateCategoryRecordTest)
889 {
890  MockBufferManager mockBuffer(0);
891  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
892 
893  // Create a category for testing
894  const std::string categoryName = "some_category";
895  const CategoryPtr category = std::make_unique<Category>(categoryName);
896  ARMNN_ASSERT(category);
897  category->m_Counters = { 11u, 23u, 5670u };
898 
899  // Create a collection of counters
900  Counters counters;
901  counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
902  CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
903  0,
904  11,
905  0,
906  0,
907  534.0003f,
908  "counter1",
909  "the first counter",
910  "millipi2",
911  0,
912  0))));
913  counters.insert(std::make_pair<uint16_t, CounterPtr>(23,
914  CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
915  1,
916  23,
917  0,
918  1,
919  534.0003f,
920  "this is counter 2",
921  "the second counter",
922  "",
923  0,
924  0))));
925  counters.insert(std::make_pair<uint16_t, CounterPtr>(5670,
926  CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
927  2,
928  5670,
929  0,
930  0,
931  534.0003f,
932  "and this is number 3",
933  "the third counter",
934  "blah_per_second",
935  0,
936  0))));
937  Counter* counter1 = counters.find(11)->second.get();
938  Counter* counter2 = counters.find(23)->second.get();
939  Counter* counter3 = counters.find(5670)->second.get();
940  ARMNN_ASSERT(counter1);
941  ARMNN_ASSERT(counter2);
942  ARMNN_ASSERT(counter3);
943  uint16_t categoryEventCount = armnn::numeric_cast<uint16_t>(counters.size());
944 
945  // Create a category record
946  SendCounterPacket::CategoryRecord categoryRecord;
947  std::string errorMessage;
948  bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
949 
950  BOOST_CHECK(result);
951  BOOST_CHECK(errorMessage.empty());
952  BOOST_CHECK(categoryRecord.size() == 79); // Size in words: header [3] + event pointer table [3] +
953  // category name [5] + event records [68 = 22 + 20 + 26]
954 
955  uint16_t categoryRecordWord1[]
956  {
957  static_cast<uint16_t>(categoryRecord[0] >> 16),
958  static_cast<uint16_t>(categoryRecord[0])
959  };
960  BOOST_CHECK(categoryRecordWord1[0] == categoryEventCount); // event_count
961  BOOST_CHECK(categoryRecordWord1[1] == 0); // reserved
962 
963  size_t uint32_t_size = sizeof(uint32_t);
964 
966  uint32_t categoryRecordBlockSize = 3u * uint32_t_size;
967  uint32_t eventPointerTableOffset = categoryRecordBlockSize; // The event pointer table is the first item in pool
968  uint32_t categoryNameOffset = eventPointerTableOffset + // Event pointer table offset
969  categoryEventCount * uint32_t_size; // The size of the event pointer table
971 
972  BOOST_CHECK(categoryRecord[1] == eventPointerTableOffset); // event_pointer_table_offset
973  BOOST_CHECK(categoryRecord[2] == categoryNameOffset); // name_offset
974  // Offsets are relative to the start of the category record
975  auto categoryRecordPool = reinterpret_cast<unsigned char*>(categoryRecord.data());
976 
977  // The event pointer table
978  uint32_t eventRecord0Offset = categoryRecordPool[eventPointerTableOffset + 0 * uint32_t_size];
979  uint32_t eventRecord1Offset = categoryRecordPool[eventPointerTableOffset + 1 * uint32_t_size];
980  uint32_t eventRecord2Offset = categoryRecordPool[eventPointerTableOffset + 2 * uint32_t_size];
981  BOOST_CHECK(eventRecord0Offset == 32);
982  BOOST_CHECK(eventRecord1Offset == 120);
983  BOOST_CHECK(eventRecord2Offset == 200);
984 
985  // The length of the SWTrace namestring (name)
986  BOOST_CHECK(categoryRecordPool[categoryNameOffset] == categoryName.size() + 1);
987  // The category name
988  BOOST_CHECK(std::memcmp(categoryRecordPool +
989  categoryNameOffset + // Offset
990  uint32_t_size, // The length of the name
991  categoryName.data(),
992  categoryName.size()) == 0); // name
993  // The null-terminator at the end of the name
994  BOOST_CHECK(categoryRecordPool[categoryNameOffset + uint32_t_size + categoryName.size()] == '\0');
995 
996  // For brevity, checking only the UIDs, max counter UIDs and names of the counters in the event records,
997  // as the event records already have a number of unit tests dedicated to them
998 
999  // Counter1 UID and max counter UID
1000  uint16_t eventRecord0Word0[2] = { 0u, 0u };
1001  std::memcpy(eventRecord0Word0, categoryRecordPool + categoryRecordBlockSize + eventRecord0Offset,
1002  sizeof(eventRecord0Word0));
1003  BOOST_CHECK(eventRecord0Word0[0] == counter1->m_Uid);
1004  BOOST_CHECK(eventRecord0Word0[1] == counter1->m_MaxCounterUid);
1005 
1006  // Counter1 name
1007  uint32_t counter1NameOffset = 0;
1008  std::memcpy(&counter1NameOffset, categoryRecordPool + eventRecord0Offset + 5u * uint32_t_size, uint32_t_size);
1009  BOOST_CHECK(counter1NameOffset == 0);
1010  // The length of the SWTrace string (name)
1011  BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
1012  categoryRecordBlockSize + // Offset to the end of the category record block
1013  8u * uint32_t_size + // Offset to the event record pool
1014  counter1NameOffset // Offset to the name of the counter
1015  ] == counter1->m_Name.size() + 1); // The length of the name including the
1016  // null-terminator
1017  // The counter1 name
1018  BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
1019  categoryRecordBlockSize + // Offset to the end of the category record block
1020  eventRecord0Offset + // Offset to the event record
1021  8u * uint32_t_size + // Offset to the event record pool
1022  counter1NameOffset + // Offset to the name of the counter
1023  uint32_t_size, // The length of the name
1024  counter1->m_Name.data(),
1025  counter1->m_Name.size()) == 0); // name
1026  // The null-terminator at the end of the counter1 name
1027  BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
1028  categoryRecordBlockSize + // Offset to the end of the category record block
1029  8u * uint32_t_size + // Offset to the event record pool
1030  counter1NameOffset + // Offset to the name of the counter
1031  uint32_t_size + // The length of the name
1032  counter1->m_Name.size() // The name of the counter
1033  ] == '\0');
1034 
1035  // Counter2 name
1036  uint32_t counter2NameOffset = 0;
1037  std::memcpy(&counter2NameOffset, categoryRecordPool +
1038  categoryRecordBlockSize +
1039  eventRecord1Offset +
1040  5u * uint32_t_size,
1041  uint32_t_size);
1042  BOOST_CHECK(counter2NameOffset == 8u * uint32_t_size );
1043  // The length of the SWTrace string (name)
1044 
1045  BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
1046  categoryRecordBlockSize +
1047  counter2NameOffset // Offset to the name of the counter
1048  ] == counter2->m_Name.size() + 1); // The length of the name including the
1049  // null-terminator
1050  // The counter2 name
1051  BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
1052  categoryRecordBlockSize + // Offset to the end of the category record block
1053  eventRecord1Offset + // Offset to the event record
1054  counter2NameOffset + // Offset to the name of the counter
1055  uint32_t_size, // The length of the name
1056  counter2->m_Name.data(),
1057  counter2->m_Name.size()) == 0); // name
1058 
1059 
1060  // The null-terminator at the end of the counter2 name
1061  BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
1062  categoryRecordBlockSize + // Offset to the end of the category record block
1063  counter2NameOffset + // Offset to the name of the counter
1064  uint32_t_size + // The length of the name
1065  counter2->m_Name.size() // The name of the counter
1066  ] == '\0');
1067 
1068  // Counter3 name
1069  uint32_t counter3NameOffset = 0;
1070  std::memcpy(&counter3NameOffset, categoryRecordPool + eventRecord2Offset + 5u * uint32_t_size, uint32_t_size);
1071  BOOST_CHECK(counter3NameOffset == 0);
1072  // The length of the SWTrace string (name)
1073  BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
1074  categoryRecordBlockSize +
1075  8u * uint32_t_size + // Offset to the event record pool
1076  counter3NameOffset // Offset to the name of the counter
1077  ] == counter3->m_Name.size() + 1); // The length of the name including the
1078  // null-terminator
1079  // The counter3 name
1080  BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
1081  categoryRecordBlockSize +
1082  eventRecord2Offset + // Offset to the event record
1083  8u * uint32_t_size + // Offset to the event record pool
1084  counter3NameOffset + // Offset to the name of the counter
1085  uint32_t_size, // The length of the name
1086  counter3->m_Name.data(),
1087  counter3->m_Name.size()) == 0); // name
1088  // The null-terminator at the end of the counter3 name
1089  BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
1090  categoryRecordBlockSize +
1091  8u * uint32_t_size + // Offset to the event record pool
1092  counter3NameOffset + // Offset to the name of the counter
1093  uint32_t_size + // The length of the name
1094  counter3->m_Name.size() // The name of the counter
1095  ] == '\0');
1096 }
1097 
1098 BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest1)
1099 {
1100  MockBufferManager mockBuffer(0);
1101  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
1102 
1103  // Create a category for testing
1104  const std::string categoryName = "some invalid category";
1105  const CategoryPtr category = std::make_unique<Category>(categoryName);
1106  BOOST_CHECK(category);
1107 
1108  // Create a category record
1109  Counters counters;
1110  SendCounterPacket::CategoryRecord categoryRecord;
1111  std::string errorMessage;
1112  bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
1113 
1114  BOOST_CHECK(!result);
1115  BOOST_CHECK(!errorMessage.empty());
1116  BOOST_CHECK(categoryRecord.empty());
1117 }
1118 
1119 BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest2)
1120 {
1121  MockBufferManager mockBuffer(0);
1122  SendCounterPacketTest sendCounterPacketTest(mockBuffer);
1123 
1124  // Create a category for testing
1125  const std::string categoryName = "some_category";
1126  const CategoryPtr category = std::make_unique<Category>(categoryName);
1127  BOOST_CHECK(category);
1128  category->m_Counters = { 11u, 23u, 5670u };
1129 
1130  // Create a collection of counters
1131  Counters counters;
1132  counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
1133  CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
1134  11,
1135  1234,
1136  0,
1137  1,
1138  534.0003f,
1139  "count€r1", // Invalid name
1140  "the first counter",
1141  "millipi2",
1142  0,
1143  0))));
1144 
1145  Counter* counter1 = counters.find(11)->second.get();
1146  BOOST_CHECK(counter1);
1147 
1148  // Create a category record
1149  SendCounterPacket::CategoryRecord categoryRecord;
1150  std::string errorMessage;
1151  bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
1152 
1153  BOOST_CHECK(!result);
1154  BOOST_CHECK(!errorMessage.empty());
1155  BOOST_CHECK(categoryRecord.empty());
1156 }
1157 
1158 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest1)
1159 {
1160  // The counter directory used for testing
1161  CounterDirectory counterDirectory;
1162 
1163  // Register a device
1164  const std::string device1Name = "device1";
1165  const Device* device1 = nullptr;
1166  BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
1167  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1168  BOOST_CHECK(device1);
1169 
1170  // Register a device
1171  const std::string device2Name = "device2";
1172  const Device* device2 = nullptr;
1173  BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
1174  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1175  BOOST_CHECK(device2);
1176 
1177  // Buffer with not enough space
1178  MockBufferManager mockBuffer(10);
1179  SendCounterPacket sendCounterPacket(mockBuffer);
1180  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory),
1182 }
1183 
1184 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest2)
1185 {
1186  // The counter directory used for testing
1187  CounterDirectory counterDirectory;
1188 
1189  // Register a device
1190  const std::string device1Name = "device1";
1191  const Device* device1 = nullptr;
1192  BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
1193  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1194  BOOST_CHECK(device1);
1195 
1196  // Register a device
1197  const std::string device2Name = "device2";
1198  const Device* device2 = nullptr;
1199  BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
1200  BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1201  BOOST_CHECK(device2);
1202 
1203  // Register a counter set
1204  const std::string counterSet1Name = "counterset1";
1205  const CounterSet* counterSet1 = nullptr;
1206  BOOST_CHECK_NO_THROW(counterSet1 = counterDirectory.RegisterCounterSet(counterSet1Name));
1207  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1208  BOOST_CHECK(counterSet1);
1209 
1210  // Register a category associated to "device1" and "counterset1"
1211  const std::string category1Name = "category1";
1212  const Category* category1 = nullptr;
1213  BOOST_CHECK_NO_THROW(category1 = counterDirectory.RegisterCategory(category1Name));
1214  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1215  BOOST_CHECK(category1);
1216 
1217  // Register a category not associated to "device2" but no counter set
1218  const std::string category2Name = "category2";
1219  const Category* category2 = nullptr;
1220  BOOST_CHECK_NO_THROW(category2 = counterDirectory.RegisterCategory(category2Name));
1221  BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
1222  BOOST_CHECK(category2);
1223 
1224  uint16_t numberOfCores = 4;
1225 
1226  // Register a counter associated to "category1"
1227  const Counter* counter1 = nullptr;
1228  BOOST_CHECK_NO_THROW(counter1 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1229  0,
1230  category1Name,
1231  0,
1232  1,
1233  123.45f,
1234  "counter1",
1235  "counter1description",
1236  std::string("counter1units"),
1237  numberOfCores));
1238  BOOST_CHECK(counterDirectory.GetCounterCount() == 4);
1239  BOOST_CHECK(counter1);
1240 
1241  // Register a counter associated to "category1"
1242  const Counter* counter2 = nullptr;
1243  BOOST_CHECK_NO_THROW(counter2 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1244  4,
1245  category1Name,
1246  1,
1247  0,
1248  330.1245656765f,
1249  "counter2",
1250  "counter2description",
1251  std::string("counter2units"),
1253  device2->m_Uid,
1254  0));
1255  BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1256  BOOST_CHECK(counter2);
1257 
1258  // Register a counter associated to "category2"
1259  const Counter* counter3 = nullptr;
1260  BOOST_CHECK_NO_THROW(counter3 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1261  5,
1262  category2Name,
1263  1,
1264  1,
1265  0.0000045399f,
1266  "counter3",
1267  "counter3description",
1269  numberOfCores,
1270  device2->m_Uid,
1271  counterSet1->m_Uid));
1272  BOOST_CHECK(counterDirectory.GetCounterCount() == 9);
1273  BOOST_CHECK(counter3);
1274 
1275  // Buffer with enough space
1276  MockBufferManager mockBuffer(1024);
1277  SendCounterPacket sendCounterPacket(mockBuffer);
1278  BOOST_CHECK_NO_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory));
1279 
1280  // Get the readable buffer
1281  auto readBuffer = mockBuffer.GetReadableBuffer();
1282 
1283  // Check the packet header
1284  const uint32_t packetHeaderWord0 = ReadUint32(readBuffer, 0);
1285  const uint32_t packetHeaderWord1 = ReadUint32(readBuffer, 4);
1286  BOOST_TEST(((packetHeaderWord0 >> 26) & 0x3F) == 0); // packet_family
1287  BOOST_TEST(((packetHeaderWord0 >> 16) & 0x3FF) == 2); // packet_id
1288  BOOST_TEST(packetHeaderWord1 == 432); // data_length
1289 
1290  // Check the body header
1291  const uint32_t bodyHeaderWord0 = ReadUint32(readBuffer, 8);
1292  const uint32_t bodyHeaderWord1 = ReadUint32(readBuffer, 12);
1293  const uint32_t bodyHeaderWord2 = ReadUint32(readBuffer, 16);
1294  const uint32_t bodyHeaderWord3 = ReadUint32(readBuffer, 20);
1295  const uint32_t bodyHeaderWord4 = ReadUint32(readBuffer, 24);
1296  const uint32_t bodyHeaderWord5 = ReadUint32(readBuffer, 28);
1297  const uint16_t deviceRecordCount = static_cast<uint16_t>(bodyHeaderWord0 >> 16);
1298  const uint16_t counterSetRecordCount = static_cast<uint16_t>(bodyHeaderWord2 >> 16);
1299  const uint16_t categoryRecordCount = static_cast<uint16_t>(bodyHeaderWord4 >> 16);
1300  BOOST_TEST(deviceRecordCount == 2); // device_records_count
1301  BOOST_TEST(bodyHeaderWord1 == bodyHeaderSize * 4); // device_records_pointer_table_offset
1302  BOOST_TEST(counterSetRecordCount == 1); // counter_set_count
1303  BOOST_TEST(bodyHeaderWord3 == 8 + bodyHeaderSize * 4); // counter_set_pointer_table_offset
1304  BOOST_TEST(categoryRecordCount == 2); // categories_count
1305  BOOST_TEST(bodyHeaderWord5 == 12 + bodyHeaderSize * 4); // categories_pointer_table_offset
1306 
1307  // Check the device records pointer table
1308  const uint32_t deviceRecordOffset0 = ReadUint32(readBuffer, 32);
1309  const uint32_t deviceRecordOffset1 = ReadUint32(readBuffer, 36);
1310  BOOST_TEST(deviceRecordOffset0 == 20); // Device record offset for "device1"
1311  BOOST_TEST(deviceRecordOffset1 == 40); // Device record offset for "device2"
1312 
1313  // Check the counter set pointer table
1314  const uint32_t counterSetRecordOffset0 = ReadUint32(readBuffer, 40);
1315  BOOST_TEST(counterSetRecordOffset0 == 52); // Counter set record offset for "counterset1"
1316 
1317  // Check the category pointer table
1318  const uint32_t categoryRecordOffset0 = ReadUint32(readBuffer, 44);
1319  const uint32_t categoryRecordOffset1 = ReadUint32(readBuffer, 48);
1320  BOOST_TEST(categoryRecordOffset0 == 72); // Category record offset for "category1"
1321  BOOST_TEST(categoryRecordOffset1 == 176); // Category record offset for "category2"
1322 
1323  // Get the device record pool offset
1324  const uint32_t uint32_t_size = sizeof(uint32_t);
1325  const uint32_t packetHeaderSize = 2u * uint32_t_size;
1326 
1327  // Device record structure/collection used for testing
1328  struct DeviceRecord
1329  {
1330  uint16_t uid;
1331  uint16_t cores;
1332  uint32_t name_offset;
1333  uint32_t name_length;
1334  std::string name;
1335  };
1336  std::vector<DeviceRecord> deviceRecords;
1337  const uint32_t deviceRecordsPointerTableOffset = packetHeaderSize +
1338  bodyHeaderWord1; // device_records_pointer_table_offset
1339 
1340  const unsigned char* readData = readBuffer->GetReadableData();
1341 
1342  uint32_t offset = 0;
1343  std::vector<uint32_t> data(800);
1344 
1345  for (uint32_t i = 0; i < 800; i+=uint32_t_size)
1346  {
1347  data[i] = ReadUint32(readBuffer, offset);
1348  offset += uint32_t_size;
1349  }
1350 
1351  std::vector<uint32_t> deviceRecordOffsets(deviceRecordCount);
1352  offset = deviceRecordsPointerTableOffset;
1353  for (uint32_t i = 0; i < deviceRecordCount; ++i)
1354  {
1355  // deviceRecordOffset is relative to the start of the deviceRecordsPointerTable
1356  deviceRecordOffsets[i] = ReadUint32(readBuffer, offset) + deviceRecordsPointerTableOffset;
1357  offset += uint32_t_size;
1358  }
1359 
1360  for (uint32_t i = 0; i < deviceRecordCount; i++)
1361  {
1362  // Collect the data for the device record
1363  const uint32_t deviceRecordWord0 = ReadUint32(readBuffer, deviceRecordOffsets[i] + 0 * uint32_t_size);
1364  const uint32_t deviceRecordWord1 = ReadUint32(readBuffer, deviceRecordOffsets[i] + 1 * uint32_t_size);
1365  DeviceRecord deviceRecord;
1366  deviceRecord.uid = static_cast<uint16_t>(deviceRecordWord0 >> 16); // uid
1367  deviceRecord.cores = static_cast<uint16_t>(deviceRecordWord0); // cores
1368  deviceRecord.name_offset = deviceRecordWord1; // name_offset
1369 
1370  uint32_t deviceRecordPoolOffset = deviceRecordOffsets[i] + // Packet body offset
1371  deviceRecord.name_offset; // Device name offset
1372  uint32_t deviceRecordNameLength = ReadUint32(readBuffer, deviceRecordPoolOffset);
1373  deviceRecord.name_length = deviceRecordNameLength; // name_length
1374  unsigned char deviceRecordNameNullTerminator = // name null-terminator
1375  ReadUint8(readBuffer, deviceRecordPoolOffset + uint32_t_size + deviceRecordNameLength - 1);
1376  BOOST_CHECK(deviceRecordNameNullTerminator == '\0');
1377  std::vector<unsigned char> deviceRecordNameBuffer(deviceRecord.name_length - 1);
1378  std::memcpy(deviceRecordNameBuffer.data(),
1379  readData + deviceRecordPoolOffset + uint32_t_size, deviceRecordNameBuffer.size());
1380  deviceRecord.name.assign(deviceRecordNameBuffer.begin(), deviceRecordNameBuffer.end()); // name
1381 
1382  deviceRecords.push_back(deviceRecord);
1383  }
1384 
1385  // Check that the device records are correct
1386  BOOST_CHECK(deviceRecords.size() == 2);
1387  for (const DeviceRecord& deviceRecord : deviceRecords)
1388  {
1389  const Device* device = counterDirectory.GetDevice(deviceRecord.uid);
1390  BOOST_CHECK(device);
1391  BOOST_CHECK(device->m_Uid == deviceRecord.uid);
1392  BOOST_CHECK(device->m_Cores == deviceRecord.cores);
1393  BOOST_CHECK(device->m_Name == deviceRecord.name);
1394  }
1395 
1396 
1397  // Counter set record structure/collection used for testing
1398  struct CounterSetRecord
1399  {
1400  uint16_t uid;
1401  uint16_t count;
1402  uint32_t name_offset;
1403  uint32_t name_length;
1404  std::string name;
1405  };
1406  std::vector<CounterSetRecord> counterSetRecords;
1407  const uint32_t counterSetRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
1408  bodyHeaderWord3; // counter_set_pointer_table_offset
1409 
1410  offset = counterSetRecordsPointerTableOffset;
1411  std::vector<uint32_t> counterSetRecordOffsets(counterSetRecordCount);
1412 
1413  for (uint32_t i = 0; i < counterSetRecordCount; ++i)
1414  {
1415  // counterSetRecordOffset is relative to the start of the dcounterSetRecordsPointerTable
1416  counterSetRecordOffsets[i] = ReadUint32(readBuffer, offset) + counterSetRecordsPointerTableOffset;
1417  offset += uint32_t_size;
1418  }
1419 
1420  for (uint32_t i = 0; i < counterSetRecordCount; i++)
1421  {
1422  // Collect the data for the counter set record
1423  const uint32_t counterSetRecordWord0 = ReadUint32(readBuffer, counterSetRecordOffsets[i] + 0 * uint32_t_size);
1424  const uint32_t counterSetRecordWord1 = ReadUint32(readBuffer, counterSetRecordOffsets[i] + 1 * uint32_t_size);
1425  CounterSetRecord counterSetRecord;
1426  counterSetRecord.uid = static_cast<uint16_t>(counterSetRecordWord0 >> 16); // uid
1427  counterSetRecord.count = static_cast<uint16_t>(counterSetRecordWord0); // count
1428  counterSetRecord.name_offset = counterSetRecordWord1; // name_offset
1429 
1430  uint32_t counterSetRecordPoolOffset = counterSetRecordOffsets[i] + // Packet body offset
1431  counterSetRecord.name_offset; // Counter set name offset
1432  uint32_t counterSetRecordNameLength = ReadUint32(readBuffer, counterSetRecordPoolOffset);
1433  counterSetRecord.name_length = counterSetRecordNameLength; // name_length
1434  unsigned char counterSetRecordNameNullTerminator = // name null-terminator
1435  ReadUint8(readBuffer, counterSetRecordPoolOffset + uint32_t_size + counterSetRecordNameLength - 1);
1436  BOOST_CHECK(counterSetRecordNameNullTerminator == '\0');
1437  std::vector<unsigned char> counterSetRecordNameBuffer(counterSetRecord.name_length - 1);
1438  std::memcpy(counterSetRecordNameBuffer.data(),
1439  readData + counterSetRecordPoolOffset + uint32_t_size, counterSetRecordNameBuffer.size());
1440  counterSetRecord.name.assign(counterSetRecordNameBuffer.begin(), counterSetRecordNameBuffer.end()); // name
1441 
1442  counterSetRecords.push_back(counterSetRecord);
1443  }
1444 
1445  // Check that the counter set records are correct
1446  BOOST_CHECK(counterSetRecords.size() == 1);
1447  for (const CounterSetRecord& counterSetRecord : counterSetRecords)
1448  {
1449  const CounterSet* counterSet = counterDirectory.GetCounterSet(counterSetRecord.uid);
1450  BOOST_CHECK(counterSet);
1451  BOOST_CHECK(counterSet->m_Uid == counterSetRecord.uid);
1452  BOOST_CHECK(counterSet->m_Count == counterSetRecord.count);
1453  BOOST_CHECK(counterSet->m_Name == counterSetRecord.name);
1454  }
1455 
1456  // Event record structure/collection used for testing
1457  struct EventRecord
1458  {
1459  uint16_t counter_uid;
1460  uint16_t max_counter_uid;
1461  uint16_t device;
1462  uint16_t counter_set;
1463  uint16_t counter_class;
1464  uint16_t interpolation;
1465  double multiplier;
1466  uint32_t name_offset;
1467  uint32_t name_length;
1468  std::string name;
1469  uint32_t description_offset;
1470  uint32_t description_length;
1471  std::string description;
1472  uint32_t units_offset;
1473  uint32_t units_length;
1474  std::string units;
1475  };
1476  // Category record structure/collection used for testing
1477  struct CategoryRecord
1478  {
1479  uint16_t event_count;
1480  uint32_t event_pointer_table_offset;
1481  uint32_t name_offset;
1482  uint32_t name_length;
1483  std::string name;
1484  std::vector<uint32_t> event_pointer_table;
1485  std::vector<EventRecord> event_records;
1486  };
1487  std::vector<CategoryRecord> categoryRecords;
1488  const uint32_t categoryRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
1489  bodyHeaderWord5; // categories_pointer_table_offset
1490 
1491  offset = categoryRecordsPointerTableOffset;
1492  std::vector<uint32_t> categoryRecordOffsets(categoryRecordCount);
1493  for (uint32_t i = 0; i < categoryRecordCount; ++i)
1494  {
1495  // categoryRecordOffset is relative to the start of the categoryRecordsPointerTable
1496  categoryRecordOffsets[i] = ReadUint32(readBuffer, offset) + categoryRecordsPointerTableOffset;
1497  offset += uint32_t_size;
1498  }
1499 
1500  for (uint32_t i = 0; i < categoryRecordCount; i++)
1501  {
1502  // Collect the data for the category record
1503  const uint32_t categoryRecordWord1 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 0 * uint32_t_size);
1504  const uint32_t categoryRecordWord2 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 1 * uint32_t_size);
1505  const uint32_t categoryRecordWord3 = ReadUint32(readBuffer, categoryRecordOffsets[i] + 2 * uint32_t_size);
1506  CategoryRecord categoryRecord;
1507  categoryRecord.event_count = static_cast<uint16_t>(categoryRecordWord1 >> 16); // event_count
1508  categoryRecord.event_pointer_table_offset = categoryRecordWord2; // event_pointer_table_offset
1509  categoryRecord.name_offset = categoryRecordWord3; // name_offset
1510 
1511  uint32_t categoryRecordNameLength = ReadUint32(readBuffer,
1512  categoryRecordOffsets[i] + categoryRecord.name_offset);
1513  categoryRecord.name_length = categoryRecordNameLength; // name_length
1514  unsigned char categoryRecordNameNullTerminator =
1515  ReadUint8(readBuffer,
1516  categoryRecordOffsets[i] +
1517  categoryRecord.name_offset +
1518  uint32_t_size +
1519  categoryRecordNameLength - 1); // name null-terminator
1520  BOOST_CHECK(categoryRecordNameNullTerminator == '\0');
1521  std::vector<unsigned char> categoryRecordNameBuffer(categoryRecord.name_length - 1);
1522  std::memcpy(categoryRecordNameBuffer.data(),
1523  readData +
1524  categoryRecordOffsets[i] +
1525  categoryRecord.name_offset +
1526  uint32_t_size,
1527  categoryRecordNameBuffer.size());
1528  categoryRecord.name.assign(categoryRecordNameBuffer.begin(), categoryRecordNameBuffer.end()); // name
1529 
1530  categoryRecord.event_pointer_table.resize(categoryRecord.event_count);
1531  offset = categoryRecordOffsets[i] + categoryRecord.event_pointer_table_offset;
1532  for (uint32_t eventOffsetIndex = 0; eventOffsetIndex < categoryRecord.event_count; ++eventOffsetIndex)
1533  {
1534  // eventRecordOffset is relative to the start of the event pointer table
1535  categoryRecord.event_pointer_table[eventOffsetIndex] = ReadUint32(readBuffer, offset) +
1536  categoryRecordOffsets[i] +
1537  categoryRecord.event_pointer_table_offset;
1538  offset += uint32_t_size;
1539  }
1540 
1541  for (uint32_t eventIndex = 0; eventIndex < categoryRecord.event_count; eventIndex++)
1542  {
1543  const uint32_t eventOffset = categoryRecord.event_pointer_table[eventIndex];
1544  // Collect the data for the event record
1545  const uint32_t eventRecordWord0 = ReadUint32(readBuffer, eventOffset + 0 * uint32_t_size);
1546  const uint32_t eventRecordWord1 = ReadUint32(readBuffer, eventOffset + 1 * uint32_t_size);
1547  const uint32_t eventRecordWord2 = ReadUint32(readBuffer, eventOffset + 2 * uint32_t_size);
1548  const uint64_t eventRecordWord34 = ReadUint64(readBuffer, eventOffset + 3 * uint32_t_size);
1549  const uint32_t eventRecordWord5 = ReadUint32(readBuffer, eventOffset + 5 * uint32_t_size);
1550  const uint32_t eventRecordWord6 = ReadUint32(readBuffer, eventOffset + 6 * uint32_t_size);
1551  const uint32_t eventRecordWord7 = ReadUint32(readBuffer, eventOffset + 7 * uint32_t_size);
1552 
1553  EventRecord eventRecord;
1554  eventRecord.counter_uid = static_cast<uint16_t>(eventRecordWord0); // counter_uid
1555  eventRecord.max_counter_uid = static_cast<uint16_t>(eventRecordWord0 >> 16); // max_counter_uid
1556  eventRecord.device = static_cast<uint16_t>(eventRecordWord1 >> 16); // device
1557  eventRecord.counter_set = static_cast<uint16_t>(eventRecordWord1); // counter_set
1558  eventRecord.counter_class = static_cast<uint16_t>(eventRecordWord2 >> 16); // class
1559  eventRecord.interpolation = static_cast<uint16_t>(eventRecordWord2); // interpolation
1560  std::memcpy(&eventRecord.multiplier, &eventRecordWord34, sizeof(eventRecord.multiplier)); // multiplier
1561  eventRecord.name_offset = static_cast<uint32_t>(eventRecordWord5); // name_offset
1562  eventRecord.description_offset = static_cast<uint32_t>(eventRecordWord6); // description_offset
1563  eventRecord.units_offset = static_cast<uint32_t>(eventRecordWord7); // units_offset
1564 
1565  uint32_t eventRecordNameLength = ReadUint32(readBuffer, eventOffset + eventRecord.name_offset);
1566  eventRecord.name_length = eventRecordNameLength; // name_length
1567  unsigned char eventRecordNameNullTerminator =
1568  ReadUint8(readBuffer,
1569  eventOffset +
1570  eventRecord.name_offset +
1571  uint32_t_size +
1572  eventRecordNameLength - 1); // name null-terminator
1573  BOOST_CHECK(eventRecordNameNullTerminator == '\0');
1574  std::vector<unsigned char> eventRecordNameBuffer(eventRecord.name_length - 1);
1575  std::memcpy(eventRecordNameBuffer.data(),
1576  readData +
1577  eventOffset +
1578  eventRecord.name_offset +
1579  uint32_t_size,
1580  eventRecordNameBuffer.size());
1581  eventRecord.name.assign(eventRecordNameBuffer.begin(), eventRecordNameBuffer.end()); // name
1582 
1583  uint32_t eventRecordDescriptionLength = ReadUint32(readBuffer,
1584  eventOffset + eventRecord.description_offset);
1585  eventRecord.description_length = eventRecordDescriptionLength; // description_length
1586  unsigned char eventRecordDescriptionNullTerminator =
1587  ReadUint8(readBuffer,
1588  eventOffset +
1589  eventRecord.description_offset +
1590  uint32_t_size +
1591  eventRecordDescriptionLength - 1); // description null-terminator
1592  BOOST_CHECK(eventRecordDescriptionNullTerminator == '\0');
1593  std::vector<unsigned char> eventRecordDescriptionBuffer(eventRecord.description_length - 1);
1594  std::memcpy(eventRecordDescriptionBuffer.data(),
1595  readData +
1596  eventOffset +
1597  eventRecord.description_offset +
1598  uint32_t_size,
1599  eventRecordDescriptionBuffer.size());
1600  eventRecord.description.assign(eventRecordDescriptionBuffer.begin(),
1601  eventRecordDescriptionBuffer.end()); // description
1602 
1603  if (eventRecord.units_offset > 0)
1604  {
1605  uint32_t eventRecordUnitsLength = ReadUint32(readBuffer,
1606  eventOffset + eventRecord.units_offset);
1607  eventRecord.units_length = eventRecordUnitsLength; // units_length
1608  unsigned char eventRecordUnitsNullTerminator =
1609  ReadUint8(readBuffer,
1610  eventOffset +
1611  eventRecord.units_offset +
1612  uint32_t_size +
1613  eventRecordUnitsLength - 1); // units null-terminator
1614  BOOST_CHECK(eventRecordUnitsNullTerminator == '\0');
1615  std::vector<unsigned char> eventRecordUnitsBuffer(eventRecord.units_length - 1);
1616  std::memcpy(eventRecordUnitsBuffer.data(),
1617  readData +
1618  eventOffset +
1619  eventRecord.units_offset +
1620  uint32_t_size,
1621  eventRecordUnitsBuffer.size());
1622  eventRecord.units.assign(eventRecordUnitsBuffer.begin(), eventRecordUnitsBuffer.end()); // units
1623  }
1624 
1625  categoryRecord.event_records.push_back(eventRecord);
1626  }
1627 
1628  categoryRecords.push_back(categoryRecord);
1629  }
1630 
1631  // Check that the category records are correct
1632  BOOST_CHECK(categoryRecords.size() == 2);
1633  for (const CategoryRecord& categoryRecord : categoryRecords)
1634  {
1635  const Category* category = counterDirectory.GetCategory(categoryRecord.name);
1636  BOOST_CHECK(category);
1637  BOOST_CHECK(category->m_Name == categoryRecord.name);
1638  BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
1639  BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
1640 
1641  // Check that the event records are correct
1642  for (const EventRecord& eventRecord : categoryRecord.event_records)
1643  {
1644  const Counter* counter = counterDirectory.GetCounter(eventRecord.counter_uid);
1645  BOOST_CHECK(counter);
1646  BOOST_CHECK(counter->m_MaxCounterUid == eventRecord.max_counter_uid);
1647  BOOST_CHECK(counter->m_DeviceUid == eventRecord.device);
1648  BOOST_CHECK(counter->m_CounterSetUid == eventRecord.counter_set);
1649  BOOST_CHECK(counter->m_Class == eventRecord.counter_class);
1650  BOOST_CHECK(counter->m_Interpolation == eventRecord.interpolation);
1651  BOOST_CHECK(counter->m_Multiplier == eventRecord.multiplier);
1652  BOOST_CHECK(counter->m_Name == eventRecord.name);
1653  BOOST_CHECK(counter->m_Description == eventRecord.description);
1654  BOOST_CHECK(counter->m_Units == eventRecord.units);
1655  }
1656  }
1657 }
1658 
1659 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest3)
1660 {
1661  // Using a mock counter directory that allows to register invalid objects
1662  MockCounterDirectory counterDirectory;
1663 
1664  // Register an invalid device
1665  const std::string deviceName = "inv@lid dev!c€";
1666  const Device* device = nullptr;
1667  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1668  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1669  BOOST_CHECK(device);
1670 
1671  // Buffer with enough space
1672  MockBufferManager mockBuffer(1024);
1673  SendCounterPacket sendCounterPacket(mockBuffer);
1674  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1675 }
1676 
1677 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest4)
1678 {
1679  // Using a mock counter directory that allows to register invalid objects
1680  MockCounterDirectory counterDirectory;
1681 
1682  // Register an invalid counter set
1683  const std::string counterSetName = "inv@lid count€rs€t";
1684  const CounterSet* counterSet = nullptr;
1685  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1686  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1687  BOOST_CHECK(counterSet);
1688 
1689  // Buffer with enough space
1690  MockBufferManager mockBuffer(1024);
1691  SendCounterPacket sendCounterPacket(mockBuffer);
1692  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1693 }
1694 
1695 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest5)
1696 {
1697  // Using a mock counter directory that allows to register invalid objects
1698  MockCounterDirectory counterDirectory;
1699 
1700  // Register an invalid category
1701  const std::string categoryName = "c@t€gory";
1702  const Category* category = nullptr;
1703  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1704  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1705  BOOST_CHECK(category);
1706 
1707  // Buffer with enough space
1708  MockBufferManager mockBuffer(1024);
1709  SendCounterPacket sendCounterPacket(mockBuffer);
1710  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1711 }
1712 
1713 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest6)
1714 {
1715  // Using a mock counter directory that allows to register invalid objects
1716  MockCounterDirectory counterDirectory;
1717 
1718  // Register an invalid device
1719  const std::string deviceName = "inv@lid dev!c€";
1720  const Device* device = nullptr;
1721  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1722  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1723  BOOST_CHECK(device);
1724 
1725  // Register an invalid counter set
1726  const std::string counterSetName = "inv@lid count€rs€t";
1727  const CounterSet* counterSet = nullptr;
1728  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1729  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1730  BOOST_CHECK(counterSet);
1731 
1732  // Register an invalid category associated to an invalid device and an invalid counter set
1733  const std::string categoryName = "c@t€gory";
1734  const Category* category = nullptr;
1735  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1736  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1737  BOOST_CHECK(category);
1738 
1739  // Buffer with enough space
1740  MockBufferManager mockBuffer(1024);
1741  SendCounterPacket sendCounterPacket(mockBuffer);
1742  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1743 }
1744 
1745 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest7)
1746 {
1747  // Using a mock counter directory that allows to register invalid objects
1748  MockCounterDirectory counterDirectory;
1749 
1750  // Register an valid device
1751  const std::string deviceName = "valid device";
1752  const Device* device = nullptr;
1753  BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1754  BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1755  BOOST_CHECK(device);
1756 
1757  // Register an valid counter set
1758  const std::string counterSetName = "valid counterset";
1759  const CounterSet* counterSet = nullptr;
1760  BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1761  BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1762  BOOST_CHECK(counterSet);
1763 
1764  // Register an valid category associated to a valid device and a valid counter set
1765  const std::string categoryName = "category";
1766  const Category* category = nullptr;
1767  BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1768  BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1769  BOOST_CHECK(category);
1770 
1771  // Register an invalid counter associated to a valid category
1772  const Counter* counter = nullptr;
1773  BOOST_CHECK_NO_THROW(counter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1774  0,
1775  categoryName,
1776  0,
1777  1,
1778  123.45f,
1779  "counter",
1780  "counter description",
1781  std::string("invalid counter units"),
1782  5,
1783  device->m_Uid,
1784  counterSet->m_Uid));
1785  BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1786  BOOST_CHECK(counter);
1787 
1788  // Buffer with enough space
1789  MockBufferManager mockBuffer(1024);
1790  SendCounterPacket sendCounterPacket(mockBuffer);
1791  BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1792 }
1793 
1794 BOOST_AUTO_TEST_CASE(SendThreadTest0)
1795 {
1796  ProfilingStateMachine profilingStateMachine;
1797  SetActiveProfilingState(profilingStateMachine);
1798 
1799  MockProfilingConnection mockProfilingConnection;
1800  MockStreamCounterBuffer mockStreamCounterBuffer(0);
1801  SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1802  SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1803 
1804  // Try to start the send thread many times, it must only start once
1805 
1806  sendThread.Start(mockProfilingConnection);
1807  BOOST_CHECK(sendThread.IsRunning());
1808  sendThread.Start(mockProfilingConnection);
1809  sendThread.Start(mockProfilingConnection);
1810  sendThread.Start(mockProfilingConnection);
1811  sendThread.Start(mockProfilingConnection);
1812  BOOST_CHECK(sendThread.IsRunning());
1813 
1814  sendThread.Stop();
1815  BOOST_CHECK(!sendThread.IsRunning());
1816 }
1817 
1818 BOOST_AUTO_TEST_CASE(SendThreadTest1)
1819 {
1820  ProfilingStateMachine profilingStateMachine;
1821  SetActiveProfilingState(profilingStateMachine);
1822 
1823  unsigned int totalWrittenSize = 0;
1824 
1825  MockProfilingConnection mockProfilingConnection;
1826  MockStreamCounterBuffer mockStreamCounterBuffer(1024);
1827  SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1828  SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1829  sendThread.Start(mockProfilingConnection);
1830 
1831  // Interleaving writes and reads to/from the buffer with pauses to test that the send thread actually waits for
1832  // something to become available for reading
1833 
1834  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1835 
1836  CounterDirectory counterDirectory;
1837  sendCounterPacket.SendStreamMetaDataPacket();
1838 
1839  totalWrittenSize += GetStreamMetaDataPacketSize();
1840 
1841  sendThread.SetReadyToRead();
1842 
1843  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1844 
1845  sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
1846 
1847  // Get the size of the Counter Directory Packet
1848  unsigned int counterDirectoryPacketSize = 32;
1849  totalWrittenSize += counterDirectoryPacketSize;
1850 
1851  sendThread.SetReadyToRead();
1852 
1853  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1854 
1855  sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
1856  {
1857  { 1u, 23u },
1858  { 33u, 1207623u }
1859  });
1860 
1861  // Get the size of the Periodic Counter Capture Packet
1862  unsigned int periodicCounterCapturePacketSize = 28;
1863  totalWrittenSize += periodicCounterCapturePacketSize;
1864 
1865  sendThread.SetReadyToRead();
1866 
1867  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1868 
1869  sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
1870  {
1871  { 211u, 923u }
1872  });
1873 
1874  // Get the size of the Periodic Counter Capture Packet
1875  periodicCounterCapturePacketSize = 22;
1876  totalWrittenSize += periodicCounterCapturePacketSize;
1877 
1878  sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
1879  {
1880  { 555u, 23u },
1881  { 556u, 6u },
1882  { 557u, 893454u },
1883  { 558u, 1456623u },
1884  { 559u, 571090u }
1885  });
1886 
1887  // Get the size of the Periodic Counter Capture Packet
1888  periodicCounterCapturePacketSize = 46;
1889  totalWrittenSize += periodicCounterCapturePacketSize;
1890 
1891  sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
1892  {
1893  { 88u, 11u },
1894  { 96u, 22u },
1895  { 97u, 33u },
1896  { 999u, 444u }
1897  });
1898 
1899  // Get the size of the Periodic Counter Capture Packet
1900  periodicCounterCapturePacketSize = 40;
1901  totalWrittenSize += periodicCounterCapturePacketSize;
1902 
1903  sendThread.SetReadyToRead();
1904 
1905  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1906 
1907  sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
1908 
1909  // Get the size of the Periodic Counter Capture Packet
1910  periodicCounterCapturePacketSize = 30;
1911  totalWrittenSize += periodicCounterCapturePacketSize;
1912 
1913  sendThread.SetReadyToRead();
1914 
1915  // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
1916  // read all what's remaining in the buffer
1917  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1918 
1919  sendThread.Stop();
1920 
1921  BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
1922  BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
1923  BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
1924 }
1925 
1926 BOOST_AUTO_TEST_CASE(SendThreadTest2)
1927 {
1928  ProfilingStateMachine profilingStateMachine;
1929  SetActiveProfilingState(profilingStateMachine);
1930 
1931  unsigned int totalWrittenSize = 0;
1932 
1933  MockProfilingConnection mockProfilingConnection;
1934  MockStreamCounterBuffer mockStreamCounterBuffer(1024);
1935  SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1936  SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1937  sendThread.Start(mockProfilingConnection);
1938 
1939  // Adding many spurious "ready to read" signals throughout the test to check that the send thread is
1940  // capable of handling unnecessary read requests
1941 
1942  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1943 
1944  sendThread.SetReadyToRead();
1945 
1946  CounterDirectory counterDirectory;
1947  sendCounterPacket.SendStreamMetaDataPacket();
1948 
1949  totalWrittenSize += GetStreamMetaDataPacketSize();
1950 
1951  sendThread.SetReadyToRead();
1952 
1953  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1954 
1955  sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
1956 
1957  // Get the size of the Counter Directory Packet
1958  unsigned int counterDirectoryPacketSize = 32;
1959  totalWrittenSize += counterDirectoryPacketSize;
1960 
1961  sendThread.SetReadyToRead();
1962  sendThread.SetReadyToRead();
1963 
1964  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1965 
1966  sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
1967  {
1968  { 1u, 23u },
1969  { 33u, 1207623u }
1970  });
1971 
1972  // Get the size of the Periodic Counter Capture Packet
1973  unsigned int periodicCounterCapturePacketSize = 28;
1974  totalWrittenSize += periodicCounterCapturePacketSize;
1975 
1976  sendThread.SetReadyToRead();
1977 
1978  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1979 
1980  sendThread.SetReadyToRead();
1981  sendThread.SetReadyToRead();
1982  sendThread.SetReadyToRead();
1983 
1984  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1985 
1986  sendThread.SetReadyToRead();
1987  sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
1988  {
1989  { 211u, 923u }
1990  });
1991 
1992  // Get the size of the Periodic Counter Capture Packet
1993  periodicCounterCapturePacketSize = 22;
1994  totalWrittenSize += periodicCounterCapturePacketSize;
1995 
1996  sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
1997  {
1998  { 555u, 23u },
1999  { 556u, 6u },
2000  { 557u, 893454u },
2001  { 558u, 1456623u },
2002  { 559u, 571090u }
2003  });
2004 
2005  // Get the size of the Periodic Counter Capture Packet
2006  periodicCounterCapturePacketSize = 46;
2007  totalWrittenSize += periodicCounterCapturePacketSize;
2008 
2009  sendThread.SetReadyToRead();
2010  sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
2011  {
2012  { 88u, 11u },
2013  { 96u, 22u },
2014  { 97u, 33u },
2015  { 999u, 444u }
2016  });
2017 
2018  // Get the size of the Periodic Counter Capture Packet
2019  periodicCounterCapturePacketSize = 40;
2020  totalWrittenSize += periodicCounterCapturePacketSize;
2021 
2022  sendThread.SetReadyToRead();
2023  sendThread.SetReadyToRead();
2024 
2025  std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
2026 
2027  sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
2028 
2029  // Get the size of the Periodic Counter Capture Packet
2030  periodicCounterCapturePacketSize = 30;
2031  totalWrittenSize += periodicCounterCapturePacketSize;
2032 
2033  sendThread.SetReadyToRead();
2034 
2035  // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
2036  // read all what's remaining in the buffer
2037  sendThread.Stop();
2038 
2039  BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
2040  BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
2041  BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
2042 }
2043 
2044 BOOST_AUTO_TEST_CASE(SendThreadTest3)
2045 {
2046  ProfilingStateMachine profilingStateMachine;
2047  SetActiveProfilingState(profilingStateMachine);
2048 
2049  unsigned int totalWrittenSize = 0;
2050 
2051  MockProfilingConnection mockProfilingConnection;
2052  MockStreamCounterBuffer mockStreamCounterBuffer(1024);
2053  SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
2054  SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
2055  sendThread.Start(mockProfilingConnection);
2056 
2057  // Not using pauses or "grace periods" to stress test the send thread
2058 
2059  sendThread.SetReadyToRead();
2060 
2061  CounterDirectory counterDirectory;
2062  sendCounterPacket.SendStreamMetaDataPacket();
2063 
2064  totalWrittenSize += GetStreamMetaDataPacketSize();
2065 
2066  sendThread.SetReadyToRead();
2067  sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2068 
2069  // Get the size of the Counter Directory Packet
2070  unsigned int counterDirectoryPacketSize =32;
2071  totalWrittenSize += counterDirectoryPacketSize;
2072 
2073  sendThread.SetReadyToRead();
2074  sendThread.SetReadyToRead();
2075  sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2076  {
2077  { 1u, 23u },
2078  { 33u, 1207623u }
2079  });
2080 
2081  // Get the size of the Periodic Counter Capture Packet
2082  unsigned int periodicCounterCapturePacketSize = 28;
2083  totalWrittenSize += periodicCounterCapturePacketSize;
2084 
2085  sendThread.SetReadyToRead();
2086  sendThread.SetReadyToRead();
2087  sendThread.SetReadyToRead();
2088  sendThread.SetReadyToRead();
2089  sendThread.SetReadyToRead();
2090  sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
2091  {
2092  { 211u, 923u }
2093  });
2094 
2095  // Get the size of the Periodic Counter Capture Packet
2096  periodicCounterCapturePacketSize = 22;
2097  totalWrittenSize += periodicCounterCapturePacketSize;
2098 
2099  sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
2100  {
2101  { 555u, 23u },
2102  { 556u, 6u },
2103  { 557u, 893454u },
2104  { 558u, 1456623u },
2105  { 559u, 571090u }
2106  });
2107 
2108  // Get the size of the Periodic Counter Capture Packet
2109  periodicCounterCapturePacketSize = 46;
2110  totalWrittenSize += periodicCounterCapturePacketSize;
2111 
2112  sendThread.SetReadyToRead();
2113  sendThread.SetReadyToRead();
2114  sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
2115  {
2116  { 88u, 11u },
2117  { 96u, 22u },
2118  { 97u, 33u },
2119  { 999u, 444u }
2120  });
2121 
2122  // Get the size of the Periodic Counter Capture Packet
2123  periodicCounterCapturePacketSize = 40;
2124  totalWrittenSize += periodicCounterCapturePacketSize;
2125 
2126  sendThread.SetReadyToRead();
2127  sendThread.SetReadyToRead();
2128  sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
2129 
2130  // Get the size of the Periodic Counter Capture Packet
2131  periodicCounterCapturePacketSize = 30;
2132  totalWrittenSize += periodicCounterCapturePacketSize;
2133 
2134  sendThread.SetReadyToRead();
2135 
2136  // Abruptly terminating the send thread, the amount of data sent may be less that the amount written (the send
2137  // thread is not guaranteed to flush the buffer)
2138  sendThread.Stop();
2139 
2140  BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
2141  BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() <= totalWrittenSize);
2142  BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= totalWrittenSize);
2143  BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetReadableSize());
2144  BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetCommittedSize());
2145 }
2146 
2147 BOOST_AUTO_TEST_CASE(SendCounterPacketTestWithSendThread)
2148 {
2149  ProfilingStateMachine profilingStateMachine;
2150  SetWaitingForAckProfilingState(profilingStateMachine);
2151 
2152  MockProfilingConnection mockProfilingConnection;
2153  BufferManager bufferManager(1, 1024);
2154  SendCounterPacket sendCounterPacket(bufferManager);
2155  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
2156  sendThread.Start(mockProfilingConnection);
2157 
2158  unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2159 
2160  sendThread.Stop();
2161 
2162  // check for packet in ProfilingConnection
2163  BOOST_CHECK(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) == 1);
2164 
2165  SetActiveProfilingState(profilingStateMachine);
2166  sendThread.Start(mockProfilingConnection);
2167 
2168  // SendCounterDirectoryPacket
2169  CounterDirectory counterDirectory;
2170  sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2171 
2172  sendThread.Stop();
2173  unsigned int counterDirectoryPacketSize = 32;
2174  // check for packet in ProfilingConnection
2175  BOOST_CHECK(mockProfilingConnection.CheckForPacket(
2176  {PacketType::CounterDirectory, counterDirectoryPacketSize}) == 1);
2177 
2178  sendThread.Start(mockProfilingConnection);
2179 
2180  // SendPeriodicCounterCapturePacket
2181  sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2182  {
2183  { 1u, 23u },
2184  { 33u, 1207623u }
2185  });
2186 
2187  sendThread.Stop();
2188 
2189  unsigned int periodicCounterCapturePacketSize = 28;
2190  BOOST_CHECK(mockProfilingConnection.CheckForPacket(
2191  {PacketType::PeriodicCounterCapture, periodicCounterCapturePacketSize}) == 1);
2192 }
2193 
2194 BOOST_AUTO_TEST_CASE(SendThreadBufferTest)
2195 {
2196  ProfilingStateMachine profilingStateMachine;
2197  SetActiveProfilingState(profilingStateMachine);
2198 
2199  MockProfilingConnection mockProfilingConnection;
2200  BufferManager bufferManager(3, 1024);
2201  SendCounterPacket sendCounterPacket(bufferManager);
2202  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
2203  sendThread.Start(mockProfilingConnection);
2204 
2205  // SendStreamMetaDataPacket
2206  sendCounterPacket.SendStreamMetaDataPacket();
2207 
2208  // Read data from the buffer
2209  // Buffer should become readable after commit by SendStreamMetaDataPacket
2210  auto packetBuffer = bufferManager.GetReadableBuffer();
2211  BOOST_TEST(packetBuffer.get());
2212 
2213  unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2214  BOOST_TEST(packetBuffer->GetSize() == streamMetadataPacketsize);
2215 
2216  // Recommit to be read by sendCounterPacket
2217  bufferManager.Commit(packetBuffer, streamMetadataPacketsize);
2218 
2219  // SendCounterDirectoryPacket
2220  CounterDirectory counterDirectory;
2221  sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2222 
2223  // SendPeriodicCounterCapturePacket
2224  sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2225  {
2226  { 1u, 23u },
2227  { 33u, 1207623u }
2228  });
2229 
2230  sendThread.Stop();
2231 
2232  // The buffer is read by the send thread so it should not be in the readable buffer.
2233  auto readBuffer = bufferManager.GetReadableBuffer();
2234  BOOST_TEST(!readBuffer);
2235 
2236  // Successfully reserved the buffer with requested size
2237  unsigned int reservedSize = 0;
2238  auto reservedBuffer = bufferManager.Reserve(512, reservedSize);
2239  BOOST_TEST(reservedSize == 512);
2240  BOOST_TEST(reservedBuffer.get());
2241 
2242  const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2243  const auto metaDataPacketCount =
2244  mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize});
2245 
2246  BOOST_TEST(metaDataPacketCount >= 1);
2247  BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::CounterDirectory, 32}) == 1);
2248  BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::PeriodicCounterCapture, 28}) == 1);
2249  // Check that we only received the packets we expected
2250  BOOST_TEST(metaDataPacketCount + 2 == writtenDataSize);
2251 }
2252 
2253 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket1)
2254 {
2255  ProfilingStateMachine profilingStateMachine;
2256 
2257  MockProfilingConnection mockProfilingConnection;
2258  BufferManager bufferManager(3, 1024);
2259  SendCounterPacket sendCounterPacket(bufferManager);
2260  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2261  sendThread.Start(mockProfilingConnection);
2262 
2263  // The profiling state is set to "Uninitialized", so the send thread should throw an exception
2264  BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
2265 }
2266 
2267 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket2)
2268 {
2269  ProfilingStateMachine profilingStateMachine;
2270  SetNotConnectedProfilingState(profilingStateMachine);
2271 
2272  MockProfilingConnection mockProfilingConnection;
2273  BufferManager bufferManager(3, 1024);
2274  SendCounterPacket sendCounterPacket(bufferManager);
2275  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2276  sendThread.Start(mockProfilingConnection);
2277 
2278  // The profiling state is set to "NotConnected", so the send thread should throw an exception
2279  BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
2280 }
2281 
2282 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket3)
2283 {
2284  ProfilingStateMachine profilingStateMachine;
2285  SetWaitingForAckProfilingState(profilingStateMachine);
2286 
2287  unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2288 
2289  MockProfilingConnection mockProfilingConnection;
2290  BufferManager bufferManager(3, 1024);
2291  SendCounterPacket sendCounterPacket(bufferManager);
2292  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2293  sendThread.Start(mockProfilingConnection);
2294 
2295  // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
2296  // Wait for sendThread to join
2297  BOOST_CHECK_NO_THROW(sendThread.Stop());
2298 
2299  // Check that the buffer contains at least one Stream Metadata packet and no other packets
2300  const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2301 
2302  BOOST_TEST(writtenDataSize >= 1u);
2303  BOOST_TEST(mockProfilingConnection.CheckForPacket(
2304  {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
2305 }
2306 
2307 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket4)
2308 {
2309  ProfilingStateMachine profilingStateMachine;
2310  SetWaitingForAckProfilingState(profilingStateMachine);
2311 
2312  unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2313 
2314  MockProfilingConnection mockProfilingConnection;
2315  BufferManager bufferManager(3, 1024);
2316  SendCounterPacket sendCounterPacket(bufferManager);
2317  SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2318  sendThread.Start(mockProfilingConnection);
2319 
2320  // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
2321  // Wait for sendThread to join
2322  sendThread.Stop();
2323 
2324  sendThread.Start(mockProfilingConnection);
2325  // Check that the profiling state is still "WaitingForAck"
2326  BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
2327 
2328  // Check that the buffer contains at least one Stream Metadata packet
2329  BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) >= 1);
2330 
2331  mockProfilingConnection.Clear();
2332 
2333  sendThread.Stop();
2334  sendThread.Start(mockProfilingConnection);
2335 
2336  // Try triggering a new buffer read
2337  sendThread.SetReadyToRead();
2338 
2339  // Wait for sendThread to join
2340  BOOST_CHECK_NO_THROW(sendThread.Stop());
2341 
2342  // Check that the profiling state is still "WaitingForAck"
2343  BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
2344 
2345  // Check that the buffer contains at least one Stream Metadata packet and no other packets
2346  const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2347 
2348  BOOST_TEST(writtenDataSize >= 1u);
2349  BOOST_TEST(mockProfilingConnection.CheckForPacket(
2350  {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
2351 }
2352 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
bool CreateCounterSetRecordTest(const CounterSetPtr &counterSet, CounterSetRecord &counterSetRecord, std::string &errorMessage)
std::vector< uint32_t > CounterSetRecord
const Category * RegisterCategory(const std::string &categoryName) override
const Counter * RegisterCounter(const BackendId &backendId, const uint16_t uid, const std::string &parentCategoryName, uint16_t counterClass, uint16_t interpolation, double multiplier, const std::string &name, const std::string &description, const Optional< std::string > &units=EmptyOptional(), const Optional< uint16_t > &numberOfCores=EmptyOptional(), const Optional< uint16_t > &deviceUid=EmptyOptional(), const Optional< uint16_t > &counterSetUid=EmptyOptional()) override
std::string GetHardwareVersion()
uint64_t ReadUint64(const IPacketBufferPtr &packetBuffer, unsigned int offset)
void SendCounterDirectoryPacket(const ICounterDirectory &counterDirectory) override
Create and write a CounterDirectoryPacket from the parameters to the buffer.
std::unordered_map< uint16_t, CounterPtr > Counters
void SendStreamMetaDataPacket() override
Create and write a StreamMetaDataPacket in the buffer.
#define ARMNN_NO_CONVERSION_WARN_END
Definition: Conversion.hpp:37
void SendCounterDirectoryPacket(const ICounterDirectory &counterDirectory) override
Create and write a CounterDirectoryPacket from the parameters to the buffer.
uint32_t GetStreamMetaDataPacketSize()
std::unique_ptr< Device > DevicePtr
std::string GetProcessName()
void SendStreamMetaDataPacket() override
Create and write a StreamMetaDataPacket in the buffer.
const Device * GetDevice(uint16_t uid) const override
bool CreateDeviceRecordTest(const DevicePtr &device, DeviceRecord &deviceRecord, std::string &errorMessage)
std::unique_ptr< CounterSet > CounterSetPtr
uint16_t ReadUint16(const IPacketBufferPtr &packetBuffer, unsigned int offset)
uint16_t GetCounterSetCount() const override
uint8_t ReadUint8(const IPacketBufferPtr &packetBuffer, unsigned int offset)
std::string GetSoftwareInfo()
void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod, const std::vector< uint16_t > &selectedCounterIds) override
Create and write a PeriodicCounterSelectionPacket from the parameters to the buffer.
bool CreateEventRecordTest(const CounterPtr &counter, EventRecord &eventRecord, std::string &errorMessage)
const Counter * RegisterCounter(const BackendId &backendId, const uint16_t uid, const std::string &parentCategoryName, uint16_t counterClass, uint16_t interpolation, double multiplier, const std::string &name, const std::string &description, const armnn::Optional< std::string > &units=armnn::EmptyOptional(), const armnn::Optional< uint16_t > &numberOfCores=armnn::EmptyOptional(), const armnn::Optional< uint16_t > &deviceUid=armnn::EmptyOptional(), const armnn::Optional< uint16_t > &counterSetUid=armnn::EmptyOptional())
uint16_t GetDeviceCount() const override
uint16_t GetCategoryCount() const override
void MarkRead(IPacketBufferPtr &packetBuffer) override
std::shared_ptr< Counter > CounterPtr
void Commit(IPacketBufferPtr &packetBuffer, unsigned int size, bool notifyConsumer=true) override
void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector &values) override
Create and write a PeriodicCounterCapturePacket from the parameters to the buffer.
const Device * RegisterDevice(const std::string &deviceName, uint16_t cores=0)
IPacketBufferPtr GetReadableBuffer() override
#define ARMNN_FALLTHROUGH
Definition: Utils.hpp:36
uint32_t ConstructHeader(uint32_t packetFamily, uint32_t packetId)
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
IPacketBufferPtr Reserve(unsigned int requestedSize, unsigned int &reservedSize) override
uint16_t GetCategoryCount() const override
const Category * RegisterCategory(const std::string &categoryName)
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
void SendPeriodicCounterCapturePacket(uint64_t timestamp, const std::vector< CounterValue > &values) override
IPacketBufferPtr GetReadableBuffer() override
#define MAX_METADATA_PACKET_LENGTH
uint16_t GetCounterCount() const override
uint32_t ReadUint32(const IPacketBufferPtr &packetBuffer, unsigned int offset)
uint16_t GetCounterSetCount() const override
#define ARMNN_NO_CONVERSION_WARN_BEGIN
Definition: Conversion.hpp:36
std::string GetSoftwareVersion()
std::vector< uint16_t > m_Counters
const Counter * GetCounter(uint16_t uid) const override
BOOST_AUTO_TEST_SUITE_END()
const Category * GetCategory(const std::string &name) const override
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
void SetReadyToRead() override
Set a "ready to read" flag in the buffer to notify the reading thread to start reading it...
Definition: SendThread.cpp:38
const Device * RegisterDevice(const std::string &deviceName, uint16_t cores=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
bool CreateCategoryRecordTest(const CategoryPtr &category, const Counters &counters, CategoryRecord &categoryRecord, std::string &errorMessage)
void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod, const std::vector< uint16_t > &selectedCounterIds) override
Create and write a PeriodicCounterSelectionPacket from the parameters to the buffer.
std::vector< uint32_t > CategoryRecord
std::unique_ptr< Category > CategoryPtr
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
const CounterSet * RegisterCounterSet(const std::string &counterSetName, uint16_t count=0)
uint16_t GetCounterCount() const override
void TransitionToState(ProfilingState newState)
long CheckForPacket(const std::pair< PacketType, uint32_t > packetInfo)
const CounterSet * RegisterCounterSet(const std::string &counterSetName, uint16_t count=0, const Optional< std::string > &parentCategoryName=EmptyOptional()) override
const CounterSet * GetCounterSet(uint16_t uid) const override
void Stop(bool rethrowSendThreadExceptions=true) override
Stop the thread.
Definition: SendThread.cpp:79
void Start(IProfilingConnection &profilingConnection) override
Start the thread.
Definition: SendThread.cpp:49
uint16_t GetDeviceCount() const override