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