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