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