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