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