2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "ProfilingMocks.hpp"
7 #include "ProfilingTestUtils.hpp"
8 #include "SendCounterPacketTests.hpp"
10 #include <BufferManager.hpp>
11 #include <CounterDirectory.hpp>
12 #include <EncodeVersion.hpp>
13 #include <ProfilingUtils.hpp>
14 #include <SendCounterPacket.hpp>
15 #include <Processes.hpp>
17 #include <armnn/Exceptions.hpp>
18 #include <armnn/Conversion.hpp>
19 #include <armnn/Utils.hpp>
21 #include <boost/test/unit_test.hpp>
22 #include <boost/numeric/conversion/cast.hpp>
26 using namespace armnn::profiling;
31 // A short delay to wait for the thread to process a packet.
32 uint16_t constexpr WAIT_UNTIL_READABLE_MS = 20;
34 void SetNotConnectedProfilingState(ProfilingStateMachine& profilingStateMachine)
36 ProfilingState currentState = profilingStateMachine.GetCurrentState();
39 case ProfilingState::WaitingForAck:
40 profilingStateMachine.TransitionToState(ProfilingState::Active);
42 case ProfilingState::Uninitialised:
44 case ProfilingState::Active:
45 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
47 case ProfilingState::NotConnected:
50 BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
54 void SetWaitingForAckProfilingState(ProfilingStateMachine& profilingStateMachine)
56 ProfilingState currentState = profilingStateMachine.GetCurrentState();
59 case ProfilingState::Uninitialised:
61 case ProfilingState::Active:
62 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
64 case ProfilingState::NotConnected:
65 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
67 case ProfilingState::WaitingForAck:
70 BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
74 void SetActiveProfilingState(ProfilingStateMachine& profilingStateMachine)
76 ProfilingState currentState = profilingStateMachine.GetCurrentState();
79 case ProfilingState::Uninitialised:
80 profilingStateMachine.TransitionToState(ProfilingState::NotConnected);
82 case ProfilingState::NotConnected:
83 profilingStateMachine.TransitionToState(ProfilingState::WaitingForAck);
85 case ProfilingState::WaitingForAck:
86 profilingStateMachine.TransitionToState(ProfilingState::Active);
88 case ProfilingState::Active:
91 BOOST_CHECK_MESSAGE(false, "Invalid profiling state");
95 } // Anonymous namespace
97 BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
99 using PacketType = MockProfilingConnection::PacketType;
101 BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
103 MockBufferManager mockBuffer(512);
104 MockSendCounterPacket mockSendCounterPacket(mockBuffer);
106 mockSendCounterPacket.SendStreamMetaDataPacket();
108 auto packetBuffer = mockBuffer.GetReadableBuffer();
109 const char* buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
111 BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
113 mockBuffer.MarkRead(packetBuffer);
115 CounterDirectory counterDirectory;
116 mockSendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
118 packetBuffer = mockBuffer.GetReadableBuffer();
119 buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
121 BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
123 mockBuffer.MarkRead(packetBuffer);
125 uint64_t timestamp = 0;
126 std::vector<CounterValue> indexValuePairs;
128 mockSendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
130 packetBuffer = mockBuffer.GetReadableBuffer();
131 buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
133 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
135 mockBuffer.MarkRead(packetBuffer);
137 uint32_t capturePeriod = 0;
138 std::vector<uint16_t> selectedCounterIds;
139 mockSendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
141 packetBuffer = mockBuffer.GetReadableBuffer();
142 buffer = reinterpret_cast<const char*>(packetBuffer->GetReadableData());
144 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
146 mockBuffer.MarkRead(packetBuffer);
149 BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest)
151 // Error no space left in buffer
152 MockBufferManager mockBuffer1(10);
153 SendCounterPacket sendPacket1(mockBuffer1);
155 uint32_t capturePeriod = 1000;
156 std::vector<uint16_t> selectedCounterIds;
157 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
160 // Packet without any counters
161 MockBufferManager mockBuffer2(512);
162 SendCounterPacket sendPacket2(mockBuffer2);
164 sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
165 auto readBuffer2 = mockBuffer2.GetReadableBuffer();
167 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
168 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
169 uint32_t period = ReadUint32(readBuffer2, 8);
171 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
172 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
173 BOOST_TEST(headerWord1 == 4); // data lenght
174 BOOST_TEST(period == 1000); // capture period
176 // Full packet message
177 MockBufferManager mockBuffer3(512);
178 SendCounterPacket sendPacket3(mockBuffer3);
180 selectedCounterIds.reserve(5);
181 selectedCounterIds.emplace_back(100);
182 selectedCounterIds.emplace_back(200);
183 selectedCounterIds.emplace_back(300);
184 selectedCounterIds.emplace_back(400);
185 selectedCounterIds.emplace_back(500);
186 sendPacket3.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
187 auto readBuffer3 = mockBuffer3.GetReadableBuffer();
189 headerWord0 = ReadUint32(readBuffer3, 0);
190 headerWord1 = ReadUint32(readBuffer3, 4);
191 period = ReadUint32(readBuffer3, 8);
193 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
194 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
195 BOOST_TEST(headerWord1 == 14); // data lenght
196 BOOST_TEST(period == 1000); // capture period
198 uint16_t counterId = 0;
199 uint32_t offset = 12;
202 for(const uint16_t& id : selectedCounterIds)
204 counterId = ReadUint16(readBuffer3, offset);
205 BOOST_TEST(counterId == id);
210 BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest)
212 ProfilingStateMachine profilingStateMachine;
214 // Error no space left in buffer
215 MockBufferManager mockBuffer1(10);
216 SendCounterPacket sendPacket1(mockBuffer1);
218 auto captureTimestamp = std::chrono::steady_clock::now();
219 uint64_t time = static_cast<uint64_t >(captureTimestamp.time_since_epoch().count());
220 std::vector<CounterValue> indexValuePairs;
222 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterCapturePacket(time, indexValuePairs),
225 // Packet without any counters
226 MockBufferManager mockBuffer2(512);
227 SendCounterPacket sendPacket2(mockBuffer2);
229 sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs);
230 auto readBuffer2 = mockBuffer2.GetReadableBuffer();
232 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
233 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
234 uint64_t readTimestamp = ReadUint64(readBuffer2, 8);
236 BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
237 BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
238 BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
239 BOOST_TEST(headerWord1 == 8); // data length
240 BOOST_TEST(time == readTimestamp); // capture period
242 // Full packet message
243 MockBufferManager mockBuffer3(512);
244 SendCounterPacket sendPacket3(mockBuffer3);
246 indexValuePairs.reserve(5);
247 indexValuePairs.emplace_back(CounterValue{0, 100});
248 indexValuePairs.emplace_back(CounterValue{1, 200});
249 indexValuePairs.emplace_back(CounterValue{2, 300});
250 indexValuePairs.emplace_back(CounterValue{3, 400});
251 indexValuePairs.emplace_back(CounterValue{4, 500});
252 sendPacket3.SendPeriodicCounterCapturePacket(time, indexValuePairs);
253 auto readBuffer3 = mockBuffer3.GetReadableBuffer();
255 headerWord0 = ReadUint32(readBuffer3, 0);
256 headerWord1 = ReadUint32(readBuffer3, 4);
257 uint64_t readTimestamp2 = ReadUint64(readBuffer3, 8);
259 BOOST_TEST(((headerWord0 >> 26) & 0x0000003F) == 3); // packet family
260 BOOST_TEST(((headerWord0 >> 19) & 0x0000007F) == 0); // packet class
261 BOOST_TEST(((headerWord0 >> 16) & 0x00000007) == 0); // packet type
262 BOOST_TEST(headerWord1 == 38); // data length
263 BOOST_TEST(time == readTimestamp2); // capture period
265 uint16_t counterIndex = 0;
266 uint32_t counterValue = 100;
267 uint32_t offset = 16;
270 for (auto it = indexValuePairs.begin(), end = indexValuePairs.end(); it != end; ++it)
272 // Check Counter Index
273 uint16_t readIndex = ReadUint16(readBuffer3, offset);
274 BOOST_TEST(counterIndex == readIndex);
278 // Check Counter Value
279 uint32_t readValue = ReadUint32(readBuffer3, offset);
280 BOOST_TEST(counterValue == readValue);
287 BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
289 using boost::numeric_cast;
291 uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
293 // Error no space left in buffer
294 MockBufferManager mockBuffer1(10);
295 SendCounterPacket sendPacket1(mockBuffer1);
296 BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion);
298 // Full metadata packet
300 std::string processName = GetProcessName().substr(0, 60);
302 uint32_t infoSize = numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1;
303 uint32_t hardwareVersionSize = numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1;
304 uint32_t softwareVersionSize = numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1;
305 uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) + 1;
307 uint32_t packetEntries = 6;
309 MockBufferManager mockBuffer2(512);
310 SendCounterPacket sendPacket2(mockBuffer2);
311 sendPacket2.SendStreamMetaDataPacket();
312 auto readBuffer2 = mockBuffer2.GetReadableBuffer();
314 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
315 uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32);
317 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
318 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id
320 uint32_t totalLength = numeric_cast<uint32_t>(2 * sizeUint32 + 10 * sizeUint32 + infoSize + hardwareVersionSize +
321 softwareVersionSize + processNameSize + sizeUint32 +
322 2 * packetEntries * sizeUint32);
324 BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length
326 uint32_t offset = sizeUint32 * 2;
327 BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::PIPE_MAGIC); // pipe_magic
328 offset += sizeUint32;
329 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version
330 offset += sizeUint32;
331 BOOST_TEST(ReadUint32(readBuffer2, offset) == MAX_METADATA_PACKET_LENGTH); // max_data_len
332 offset += sizeUint32;
333 int pid = armnnUtils::Processes::GetCurrentId();
334 BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast<uint32_t>(pid));
335 offset += sizeUint32;
336 uint32_t poolOffset = 10 * sizeUint32;
337 BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_info
338 offset += sizeUint32;
339 poolOffset += infoSize;
340 BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_hw_version
341 offset += sizeUint32;
342 poolOffset += hardwareVersionSize;
343 BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_sw_version
344 offset += sizeUint32;
345 poolOffset += softwareVersionSize;
346 BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_process_name
347 offset += sizeUint32;
348 poolOffset += processNameSize;
349 BOOST_TEST(ReadUint32(readBuffer2, offset) == poolOffset); // offset_packet_version_table
350 offset += sizeUint32;
351 BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved
353 const unsigned char* readData2 = readBuffer2->GetReadableData();
355 offset += sizeUint32;
358 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareInfo().c_str()) == 0);
362 if (hardwareVersionSize)
364 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetHardwareVersion().c_str()) == 0);
365 offset += hardwareVersionSize;
368 if (softwareVersionSize)
370 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetSoftwareVersion().c_str()) == 0);
371 offset += softwareVersionSize;
376 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readData2[offset]), GetProcessName().c_str()) == 0);
377 offset += processNameSize;
382 BOOST_TEST((ReadUint32(readBuffer2, offset) >> 16) == packetEntries);
383 offset += sizeUint32;
384 for (uint32_t i = 0; i < packetEntries - 1; ++i)
386 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 0);
387 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == i);
388 offset += sizeUint32;
389 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
390 offset += sizeUint32;
393 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 1);
394 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == 0);
395 offset += sizeUint32;
396 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
397 offset += sizeUint32;
400 BOOST_TEST(offset == totalLength);
403 BOOST_AUTO_TEST_CASE(CreateDeviceRecordTest)
405 MockBufferManager mockBuffer(0);
406 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
408 // Create a device for testing
409 uint16_t deviceUid = 27;
410 const std::string deviceName = "some_device";
411 uint16_t deviceCores = 3;
412 const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
414 // Create a device record
415 SendCounterPacket::DeviceRecord deviceRecord;
416 std::string errorMessage;
417 bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
420 BOOST_CHECK(errorMessage.empty());
421 BOOST_CHECK(deviceRecord.size() == 6); // Size in words: header [2] + device name [4]
423 uint16_t deviceRecordWord0[]
425 static_cast<uint16_t>(deviceRecord[0] >> 16),
426 static_cast<uint16_t>(deviceRecord[0])
428 BOOST_CHECK(deviceRecordWord0[0] == deviceUid); // uid
429 BOOST_CHECK(deviceRecordWord0[1] == deviceCores); // cores
430 BOOST_CHECK(deviceRecord[1] == 0); // name_offset
431 BOOST_CHECK(deviceRecord[2] == deviceName.size() + 1); // The length of the SWTrace string (name)
432 BOOST_CHECK(std::memcmp(deviceRecord.data() + 3, deviceName.data(), deviceName.size()) == 0); // name
435 BOOST_AUTO_TEST_CASE(CreateInvalidDeviceRecordTest)
437 MockBufferManager mockBuffer(0);
438 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
440 // Create a device for testing
441 uint16_t deviceUid = 27;
442 const std::string deviceName = "some€£invalid‡device";
443 uint16_t deviceCores = 3;
444 const DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, deviceCores);
446 // Create a device record
447 SendCounterPacket::DeviceRecord deviceRecord;
448 std::string errorMessage;
449 bool result = sendCounterPacketTest.CreateDeviceRecordTest(device, deviceRecord, errorMessage);
451 BOOST_CHECK(!result);
452 BOOST_CHECK(!errorMessage.empty());
453 BOOST_CHECK(deviceRecord.empty());
456 BOOST_AUTO_TEST_CASE(CreateCounterSetRecordTest)
458 MockBufferManager mockBuffer(0);
459 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
461 // Create a counter set for testing
462 uint16_t counterSetUid = 27;
463 const std::string counterSetName = "some_counter_set";
464 uint16_t counterSetCount = 3421;
465 const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
467 // Create a counter set record
468 SendCounterPacket::CounterSetRecord counterSetRecord;
469 std::string errorMessage;
470 bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
473 BOOST_CHECK(errorMessage.empty());
474 BOOST_CHECK(counterSetRecord.size() == 8); // Size in words: header [2] + counter set name [6]
476 uint16_t counterSetRecordWord0[]
478 static_cast<uint16_t>(counterSetRecord[0] >> 16),
479 static_cast<uint16_t>(counterSetRecord[0])
481 BOOST_CHECK(counterSetRecordWord0[0] == counterSetUid); // uid
482 BOOST_CHECK(counterSetRecordWord0[1] == counterSetCount); // cores
483 BOOST_CHECK(counterSetRecord[1] == 0); // name_offset
484 BOOST_CHECK(counterSetRecord[2] == counterSetName.size() + 1); // The length of the SWTrace string (name)
485 BOOST_CHECK(std::memcmp(counterSetRecord.data() + 3, counterSetName.data(), counterSetName.size()) == 0); // name
488 BOOST_AUTO_TEST_CASE(CreateInvalidCounterSetRecordTest)
490 MockBufferManager mockBuffer(0);
491 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
493 // Create a counter set for testing
494 uint16_t counterSetUid = 27;
495 const std::string counterSetName = "some invalid_counter€£set";
496 uint16_t counterSetCount = 3421;
497 const CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, counterSetCount);
499 // Create a counter set record
500 SendCounterPacket::CounterSetRecord counterSetRecord;
501 std::string errorMessage;
502 bool result = sendCounterPacketTest.CreateCounterSetRecordTest(counterSet, counterSetRecord, errorMessage);
504 BOOST_CHECK(!result);
505 BOOST_CHECK(!errorMessage.empty());
506 BOOST_CHECK(counterSetRecord.empty());
509 BOOST_AUTO_TEST_CASE(CreateEventRecordTest)
511 MockBufferManager mockBuffer(0);
512 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
514 // Create a counter for testing
515 uint16_t counterUid = 7256;
516 uint16_t maxCounterUid = 132;
517 uint16_t deviceUid = 132;
518 uint16_t counterSetUid = 4497;
519 uint16_t counterClass = 1;
520 uint16_t counterInterpolation = 1;
521 double counterMultiplier = 1234.567f;
522 const std::string counterName = "some_valid_counter";
523 const std::string counterDescription = "a_counter_for_testing";
524 const std::string counterUnits = "Mrads2";
525 const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
529 counterInterpolation,
536 ARMNN_ASSERT(counter);
538 // Create an event record
539 SendCounterPacket::EventRecord eventRecord;
540 std::string errorMessage;
541 bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
544 BOOST_CHECK(errorMessage.empty());
545 BOOST_CHECK(eventRecord.size() == 24); // Size in words: header [8] + counter name [6] + description [7] + units [3]
547 uint16_t eventRecordWord0[]
549 static_cast<uint16_t>(eventRecord[0] >> 16),
550 static_cast<uint16_t>(eventRecord[0])
552 uint16_t eventRecordWord1[]
554 static_cast<uint16_t>(eventRecord[1] >> 16),
555 static_cast<uint16_t>(eventRecord[1])
557 uint16_t eventRecordWord2[]
559 static_cast<uint16_t>(eventRecord[2] >> 16),
560 static_cast<uint16_t>(eventRecord[2])
562 uint32_t eventRecordWord34[]
567 BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
568 BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
569 BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
570 BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
571 BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
572 BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
573 BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
575 ARMNN_NO_CONVERSION_WARN_BEGIN
576 uint32_t counterNameOffset = 0; // The name is the first item in pool
577 uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
578 4u + // Counter name length (uint32_t)
579 counterName.size() + // 18u
580 1u + // Null-terminator
581 1u; // Rounding to the next word
582 size_t counterUnitsOffset = counterDescriptionOffset + // Counter description offset
583 4u + // Counter description length (uint32_t)
584 counterDescription.size() + // 21u
585 1u + // Null-terminator
586 2u; // Rounding to the next word
587 ARMNN_NO_CONVERSION_WARN_END
589 BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
590 BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
591 BOOST_CHECK(eventRecord[7] == counterUnitsOffset); // units_offset
593 auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data() + 8u); // The start of the pool
594 size_t uint32_t_size = sizeof(uint32_t);
596 // The length of the SWTrace string (name)
597 BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
599 BOOST_CHECK(std::memcmp(eventRecordPool +
600 counterNameOffset + // Offset
601 uint32_t_size /* The length of the name */,
603 counterName.size()) == 0); // name
604 // The null-terminator at the end of the name
605 BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
607 // The length of the SWTrace string (description)
608 BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
609 // The counter description
610 BOOST_CHECK(std::memcmp(eventRecordPool +
611 counterDescriptionOffset + // Offset
612 uint32_t_size /* The length of the description */,
613 counterDescription.data(),
614 counterDescription.size()) == 0); // description
615 // The null-terminator at the end of the description
616 BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
618 // The length of the SWTrace namestring (units)
619 BOOST_CHECK(eventRecordPool[counterUnitsOffset] == counterUnits.size() + 1);
621 BOOST_CHECK(std::memcmp(eventRecordPool +
622 counterUnitsOffset + // Offset
623 uint32_t_size /* The length of the units */,
625 counterUnits.size()) == 0); // units
626 // The null-terminator at the end of the units
627 BOOST_CHECK(eventRecordPool[counterUnitsOffset + uint32_t_size + counterUnits.size()] == '\0');
630 BOOST_AUTO_TEST_CASE(CreateEventRecordNoUnitsTest)
632 MockBufferManager mockBuffer(0);
633 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
635 // Create a counter for testing
636 uint16_t counterUid = 44312;
637 uint16_t maxCounterUid = 345;
638 uint16_t deviceUid = 101;
639 uint16_t counterSetUid = 34035;
640 uint16_t counterClass = 0;
641 uint16_t counterInterpolation = 1;
642 double counterMultiplier = 4435.0023f;
643 const std::string counterName = "some_valid_counter";
644 const std::string counterDescription = "a_counter_for_testing";
645 const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
649 counterInterpolation,
656 ARMNN_ASSERT(counter);
658 // Create an event record
659 SendCounterPacket::EventRecord eventRecord;
660 std::string errorMessage;
661 bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
664 BOOST_CHECK(errorMessage.empty());
665 BOOST_CHECK(eventRecord.size() == 21); // Size in words: header [8] + counter name [6] + description [7]
667 uint16_t eventRecordWord0[]
669 static_cast<uint16_t>(eventRecord[0] >> 16),
670 static_cast<uint16_t>(eventRecord[0])
672 uint16_t eventRecordWord1[]
674 static_cast<uint16_t>(eventRecord[1] >> 16),
675 static_cast<uint16_t>(eventRecord[1])
677 uint16_t eventRecordWord2[]
679 static_cast<uint16_t>(eventRecord[2] >> 16),
680 static_cast<uint16_t>(eventRecord[2])
682 uint32_t eventRecordWord34[]
687 BOOST_CHECK(eventRecordWord0[0] == maxCounterUid); // max_counter_uid
688 BOOST_CHECK(eventRecordWord0[1] == counterUid); // counter_uid
689 BOOST_CHECK(eventRecordWord1[0] == deviceUid); // device
690 BOOST_CHECK(eventRecordWord1[1] == counterSetUid); // counter_set
691 BOOST_CHECK(eventRecordWord2[0] == counterClass); // class
692 BOOST_CHECK(eventRecordWord2[1] == counterInterpolation); // interpolation
693 BOOST_CHECK(std::memcmp(eventRecordWord34, &counterMultiplier, sizeof(counterMultiplier)) == 0); // multiplier
695 ARMNN_NO_CONVERSION_WARN_BEGIN
696 uint32_t counterNameOffset = 0; // The name is the first item in pool
697 uint32_t counterDescriptionOffset = counterNameOffset + // Counter name offset
698 4u + // Counter name length (uint32_t)
699 counterName.size() + // 18u
700 1u + // Null-terminator
701 1u; // Rounding to the next word
702 ARMNN_NO_CONVERSION_WARN_END
704 BOOST_CHECK(eventRecord[5] == counterNameOffset); // name_offset
705 BOOST_CHECK(eventRecord[6] == counterDescriptionOffset); // description_offset
706 BOOST_CHECK(eventRecord[7] == 0); // units_offset
708 auto eventRecordPool = reinterpret_cast<unsigned char*>(eventRecord.data() + 8u); // The start of the pool
709 size_t uint32_t_size = sizeof(uint32_t);
711 // The length of the SWTrace string (name)
712 BOOST_CHECK(eventRecordPool[counterNameOffset] == counterName.size() + 1);
714 BOOST_CHECK(std::memcmp(eventRecordPool +
715 counterNameOffset + // Offset
716 uint32_t_size, // The length of the name
718 counterName.size()) == 0); // name
719 // The null-terminator at the end of the name
720 BOOST_CHECK(eventRecordPool[counterNameOffset + uint32_t_size + counterName.size()] == '\0');
722 // The length of the SWTrace string (description)
723 BOOST_CHECK(eventRecordPool[counterDescriptionOffset] == counterDescription.size() + 1);
724 // The counter description
725 BOOST_CHECK(std::memcmp(eventRecordPool +
726 counterDescriptionOffset + // Offset
727 uint32_t_size, // The length of the description
728 counterDescription.data(),
729 counterDescription.size()) == 0); // description
730 // The null-terminator at the end of the description
731 BOOST_CHECK(eventRecordPool[counterDescriptionOffset + uint32_t_size + counterDescription.size()] == '\0');
734 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest1)
736 MockBufferManager mockBuffer(0);
737 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
739 // Create a counter for testing
740 uint16_t counterUid = 7256;
741 uint16_t maxCounterUid = 132;
742 uint16_t deviceUid = 132;
743 uint16_t counterSetUid = 4497;
744 uint16_t counterClass = 1;
745 uint16_t counterInterpolation = 1;
746 double counterMultiplier = 1234.567f;
747 const std::string counterName = "some_invalid_counter £££"; // Invalid name
748 const std::string counterDescription = "a_counter_for_testing";
749 const std::string counterUnits = "Mrads2";
750 const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
754 counterInterpolation,
761 ARMNN_ASSERT(counter);
763 // Create an event record
764 SendCounterPacket::EventRecord eventRecord;
765 std::string errorMessage;
766 bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
768 BOOST_CHECK(!result);
769 BOOST_CHECK(!errorMessage.empty());
770 BOOST_CHECK(eventRecord.empty());
773 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest2)
775 MockBufferManager mockBuffer(0);
776 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
778 // Create a counter for testing
779 uint16_t counterUid = 7256;
780 uint16_t maxCounterUid = 132;
781 uint16_t deviceUid = 132;
782 uint16_t counterSetUid = 4497;
783 uint16_t counterClass = 1;
784 uint16_t counterInterpolation = 1;
785 double counterMultiplier = 1234.567f;
786 const std::string counterName = "some_invalid_counter";
787 const std::string counterDescription = "an invalid d€scription"; // Invalid description
788 const std::string counterUnits = "Mrads2";
789 const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
793 counterInterpolation,
800 ARMNN_ASSERT(counter);
802 // Create an event record
803 SendCounterPacket::EventRecord eventRecord;
804 std::string errorMessage;
805 bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
807 BOOST_CHECK(!result);
808 BOOST_CHECK(!errorMessage.empty());
809 BOOST_CHECK(eventRecord.empty());
812 BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest3)
814 MockBufferManager mockBuffer(0);
815 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
817 // Create a counter for testing
818 uint16_t counterUid = 7256;
819 uint16_t maxCounterUid = 132;
820 uint16_t deviceUid = 132;
821 uint16_t counterSetUid = 4497;
822 uint16_t counterClass = 1;
823 uint16_t counterInterpolation = 1;
824 double counterMultiplier = 1234.567f;
825 const std::string counterName = "some_invalid_counter";
826 const std::string counterDescription = "a valid description";
827 const std::string counterUnits = "Mrad s2"; // Invalid units
828 const CounterPtr counter = std::make_unique<Counter>(armnn::profiling::BACKEND_ID,
832 counterInterpolation,
839 ARMNN_ASSERT(counter);
841 // Create an event record
842 SendCounterPacket::EventRecord eventRecord;
843 std::string errorMessage;
844 bool result = sendCounterPacketTest.CreateEventRecordTest(counter, eventRecord, errorMessage);
846 BOOST_CHECK(!result);
847 BOOST_CHECK(!errorMessage.empty());
848 BOOST_CHECK(eventRecord.empty());
851 BOOST_AUTO_TEST_CASE(CreateCategoryRecordTest)
853 MockBufferManager mockBuffer(0);
854 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
856 // Create a category for testing
857 const std::string categoryName = "some_category";
858 const CategoryPtr category = std::make_unique<Category>(categoryName);
859 ARMNN_ASSERT(category);
860 category->m_Counters = { 11u, 23u, 5670u };
862 // Create a collection of counters
864 counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
865 CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
876 counters.insert(std::make_pair<uint16_t, CounterPtr>(23,
877 CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
884 "the second counter",
888 counters.insert(std::make_pair<uint16_t, CounterPtr>(5670,
889 CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
895 "and this is number 3",
900 Counter* counter1 = counters.find(11)->second.get();
901 Counter* counter2 = counters.find(23)->second.get();
902 Counter* counter3 = counters.find(5670)->second.get();
903 ARMNN_ASSERT(counter1);
904 ARMNN_ASSERT(counter2);
905 ARMNN_ASSERT(counter3);
906 uint16_t categoryEventCount = boost::numeric_cast<uint16_t>(counters.size());
908 // Create a category record
909 SendCounterPacket::CategoryRecord categoryRecord;
910 std::string errorMessage;
911 bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
914 BOOST_CHECK(errorMessage.empty());
915 BOOST_CHECK(categoryRecord.size() == 79); // Size in words: header [3] + event pointer table [3] +
916 // category name [5] + event records [68 = 22 + 20 + 26]
918 uint16_t categoryRecordWord1[]
920 static_cast<uint16_t>(categoryRecord[0] >> 16),
921 static_cast<uint16_t>(categoryRecord[0])
923 BOOST_CHECK(categoryRecordWord1[0] == categoryEventCount); // event_count
924 BOOST_CHECK(categoryRecordWord1[1] == 0); // reserved
926 size_t uint32_t_size = sizeof(uint32_t);
928 ARMNN_NO_CONVERSION_WARN_BEGIN
929 uint32_t eventPointerTableOffset = 0; // The event pointer table is the first item in pool
930 uint32_t categoryNameOffset = eventPointerTableOffset + // Event pointer table offset
931 categoryEventCount * uint32_t_size; // The size of the event pointer table
932 ARMNN_NO_CONVERSION_WARN_END
934 BOOST_CHECK(categoryRecord[1] == eventPointerTableOffset); // event_pointer_table_offset
935 BOOST_CHECK(categoryRecord[2] == categoryNameOffset); // name_offset
937 auto categoryRecordPool = reinterpret_cast<unsigned char*>(categoryRecord.data() + 3u); // The start of the pool
939 // The event pointer table
940 uint32_t eventRecord0Offset = categoryRecordPool[eventPointerTableOffset + 0 * uint32_t_size];
941 uint32_t eventRecord1Offset = categoryRecordPool[eventPointerTableOffset + 1 * uint32_t_size];
942 uint32_t eventRecord2Offset = categoryRecordPool[eventPointerTableOffset + 2 * uint32_t_size];
943 BOOST_CHECK(eventRecord0Offset == 32);
944 BOOST_CHECK(eventRecord1Offset == 120);
945 BOOST_CHECK(eventRecord2Offset == 200);
947 // The length of the SWTrace namestring (name)
948 BOOST_CHECK(categoryRecordPool[categoryNameOffset] == categoryName.size() + 1);
950 BOOST_CHECK(std::memcmp(categoryRecordPool +
951 categoryNameOffset + // Offset
952 uint32_t_size, // The length of the name
954 categoryName.size()) == 0); // name
955 // The null-terminator at the end of the name
956 BOOST_CHECK(categoryRecordPool[categoryNameOffset + uint32_t_size + categoryName.size()] == '\0');
958 // For brevity, checking only the UIDs, max counter UIDs and names of the counters in the event records,
959 // as the event records already have a number of unit tests dedicated to them
961 // Counter1 UID and max counter UID
962 uint16_t eventRecord0Word0[2] = { 0u, 0u };
963 std::memcpy(eventRecord0Word0, categoryRecordPool + eventRecord0Offset, sizeof(eventRecord0Word0));
964 BOOST_CHECK(eventRecord0Word0[0] == counter1->m_Uid);
965 BOOST_CHECK(eventRecord0Word0[1] == counter1->m_MaxCounterUid);
968 uint32_t counter1NameOffset = 0;
969 std::memcpy(&counter1NameOffset, categoryRecordPool + eventRecord0Offset + 5u * uint32_t_size, uint32_t_size);
970 BOOST_CHECK(counter1NameOffset == 0);
971 // The length of the SWTrace string (name)
972 BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
973 8u * uint32_t_size + // Offset to the event record pool
974 counter1NameOffset // Offset to the name of the counter
975 ] == counter1->m_Name.size() + 1); // The length of the name including the
978 BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
979 eventRecord0Offset + // Offset to the event record
980 8u * uint32_t_size + // Offset to the event record pool
981 counter1NameOffset + // Offset to the name of the counter
982 uint32_t_size, // The length of the name
983 counter1->m_Name.data(),
984 counter1->m_Name.size()) == 0); // name
985 // The null-terminator at the end of the counter1 name
986 BOOST_CHECK(categoryRecordPool[eventRecord0Offset + // Offset to the event record
987 8u * uint32_t_size + // Offset to the event record pool
988 counter1NameOffset + // Offset to the name of the counter
989 uint32_t_size + // The length of the name
990 counter1->m_Name.size() // The name of the counter
994 uint32_t counter2NameOffset = 0;
995 std::memcpy(&counter2NameOffset, categoryRecordPool + eventRecord1Offset + 5u * uint32_t_size, uint32_t_size);
996 BOOST_CHECK(counter2NameOffset == 0);
997 // The length of the SWTrace string (name)
998 BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
999 8u * uint32_t_size + // Offset to the event record pool
1000 counter2NameOffset // Offset to the name of the counter
1001 ] == counter2->m_Name.size() + 1); // The length of the name including the
1003 // The counter2 name
1004 BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
1005 eventRecord1Offset + // Offset to the event record
1006 8u * uint32_t_size + // Offset to the event record pool
1007 counter2NameOffset + // Offset to the name of the counter
1008 uint32_t_size, // The length of the name
1009 counter2->m_Name.data(),
1010 counter2->m_Name.size()) == 0); // name
1011 // The null-terminator at the end of the counter2 name
1012 BOOST_CHECK(categoryRecordPool[eventRecord1Offset + // Offset to the event record
1013 8u * uint32_t_size + // Offset to the event record pool
1014 counter2NameOffset + // Offset to the name of the counter
1015 uint32_t_size + // The length of the name
1016 counter2->m_Name.size() // The name of the counter
1020 uint32_t counter3NameOffset = 0;
1021 std::memcpy(&counter3NameOffset, categoryRecordPool + eventRecord2Offset + 5u * uint32_t_size, uint32_t_size);
1022 BOOST_CHECK(counter3NameOffset == 0);
1023 // The length of the SWTrace string (name)
1024 BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
1025 8u * uint32_t_size + // Offset to the event record pool
1026 counter3NameOffset // Offset to the name of the counter
1027 ] == counter3->m_Name.size() + 1); // The length of the name including the
1029 // The counter3 name
1030 BOOST_CHECK(std::memcmp(categoryRecordPool + // The beginning of the category pool
1031 eventRecord2Offset + // Offset to the event record
1032 8u * uint32_t_size + // Offset to the event record pool
1033 counter3NameOffset + // Offset to the name of the counter
1034 uint32_t_size, // The length of the name
1035 counter3->m_Name.data(),
1036 counter3->m_Name.size()) == 0); // name
1037 // The null-terminator at the end of the counter3 name
1038 BOOST_CHECK(categoryRecordPool[eventRecord2Offset + // Offset to the event record
1039 8u * uint32_t_size + // Offset to the event record pool
1040 counter3NameOffset + // Offset to the name of the counter
1041 uint32_t_size + // The length of the name
1042 counter3->m_Name.size() // The name of the counter
1046 BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest1)
1048 MockBufferManager mockBuffer(0);
1049 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
1051 // Create a category for testing
1052 const std::string categoryName = "some invalid category";
1053 const CategoryPtr category = std::make_unique<Category>(categoryName);
1054 BOOST_CHECK(category);
1056 // Create a category record
1058 SendCounterPacket::CategoryRecord categoryRecord;
1059 std::string errorMessage;
1060 bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
1062 BOOST_CHECK(!result);
1063 BOOST_CHECK(!errorMessage.empty());
1064 BOOST_CHECK(categoryRecord.empty());
1067 BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest2)
1069 MockBufferManager mockBuffer(0);
1070 SendCounterPacketTest sendCounterPacketTest(mockBuffer);
1072 // Create a category for testing
1073 const std::string categoryName = "some_category";
1074 const CategoryPtr category = std::make_unique<Category>(categoryName);
1075 BOOST_CHECK(category);
1076 category->m_Counters = { 11u, 23u, 5670u };
1078 // Create a collection of counters
1080 counters.insert(std::make_pair<uint16_t, CounterPtr>(11,
1081 CounterPtr(new Counter(armnn::profiling::BACKEND_ID,
1087 "count€r1", // Invalid name
1088 "the first counter",
1093 Counter* counter1 = counters.find(11)->second.get();
1094 BOOST_CHECK(counter1);
1096 // Create a category record
1097 SendCounterPacket::CategoryRecord categoryRecord;
1098 std::string errorMessage;
1099 bool result = sendCounterPacketTest.CreateCategoryRecordTest(category, counters, categoryRecord, errorMessage);
1101 BOOST_CHECK(!result);
1102 BOOST_CHECK(!errorMessage.empty());
1103 BOOST_CHECK(categoryRecord.empty());
1106 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest1)
1108 // The counter directory used for testing
1109 CounterDirectory counterDirectory;
1111 // Register a device
1112 const std::string device1Name = "device1";
1113 const Device* device1 = nullptr;
1114 BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
1115 BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1116 BOOST_CHECK(device1);
1118 // Register a device
1119 const std::string device2Name = "device2";
1120 const Device* device2 = nullptr;
1121 BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
1122 BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1123 BOOST_CHECK(device2);
1125 // Buffer with not enough space
1126 MockBufferManager mockBuffer(10);
1127 SendCounterPacket sendCounterPacket(mockBuffer);
1128 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory),
1129 armnn::profiling::BufferExhaustion);
1132 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest2)
1134 // The counter directory used for testing
1135 CounterDirectory counterDirectory;
1137 // Register a device
1138 const std::string device1Name = "device1";
1139 const Device* device1 = nullptr;
1140 BOOST_CHECK_NO_THROW(device1 = counterDirectory.RegisterDevice(device1Name, 3));
1141 BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1142 BOOST_CHECK(device1);
1144 // Register a device
1145 const std::string device2Name = "device2";
1146 const Device* device2 = nullptr;
1147 BOOST_CHECK_NO_THROW(device2 = counterDirectory.RegisterDevice(device2Name));
1148 BOOST_CHECK(counterDirectory.GetDeviceCount() == 2);
1149 BOOST_CHECK(device2);
1151 // Register a counter set
1152 const std::string counterSet1Name = "counterset1";
1153 const CounterSet* counterSet1 = nullptr;
1154 BOOST_CHECK_NO_THROW(counterSet1 = counterDirectory.RegisterCounterSet(counterSet1Name));
1155 BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1156 BOOST_CHECK(counterSet1);
1158 // Register a category associated to "device1" and "counterset1"
1159 const std::string category1Name = "category1";
1160 const Category* category1 = nullptr;
1161 BOOST_CHECK_NO_THROW(category1 = counterDirectory.RegisterCategory(category1Name));
1162 BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1163 BOOST_CHECK(category1);
1165 // Register a category not associated to "device2" but no counter set
1166 const std::string category2Name = "category2";
1167 const Category* category2 = nullptr;
1168 BOOST_CHECK_NO_THROW(category2 = counterDirectory.RegisterCategory(category2Name));
1169 BOOST_CHECK(counterDirectory.GetCategoryCount() == 2);
1170 BOOST_CHECK(category2);
1172 uint16_t numberOfCores = 4;
1174 // Register a counter associated to "category1"
1175 const Counter* counter1 = nullptr;
1176 BOOST_CHECK_NO_THROW(counter1 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1183 "counter1description",
1184 std::string("counter1units"),
1186 BOOST_CHECK(counterDirectory.GetCounterCount() == 4);
1187 BOOST_CHECK(counter1);
1189 // Register a counter associated to "category1"
1190 const Counter* counter2 = nullptr;
1191 BOOST_CHECK_NO_THROW(counter2 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1198 "counter2description",
1199 std::string("counter2units"),
1200 armnn::EmptyOptional(),
1203 BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1204 BOOST_CHECK(counter2);
1206 // Register a counter associated to "category2"
1207 const Counter* counter3 = nullptr;
1208 BOOST_CHECK_NO_THROW(counter3 = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1215 "counter3description",
1216 armnn::EmptyOptional(),
1219 counterSet1->m_Uid));
1220 BOOST_CHECK(counterDirectory.GetCounterCount() == 9);
1221 BOOST_CHECK(counter3);
1223 // Buffer with enough space
1224 MockBufferManager mockBuffer(1024);
1225 SendCounterPacket sendCounterPacket(mockBuffer);
1226 BOOST_CHECK_NO_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory));
1228 // Get the readable buffer
1229 auto readBuffer = mockBuffer.GetReadableBuffer();
1231 // Check the packet header
1232 const uint32_t packetHeaderWord0 = ReadUint32(readBuffer, 0);
1233 const uint32_t packetHeaderWord1 = ReadUint32(readBuffer, 4);
1234 BOOST_TEST(((packetHeaderWord0 >> 26) & 0x3F) == 0); // packet_family
1235 BOOST_TEST(((packetHeaderWord0 >> 16) & 0x3FF) == 2); // packet_id
1236 BOOST_TEST(packetHeaderWord1 == 432); // data_length
1238 // Check the body header
1239 const uint32_t bodyHeaderWord0 = ReadUint32(readBuffer, 8);
1240 const uint32_t bodyHeaderWord1 = ReadUint32(readBuffer, 12);
1241 const uint32_t bodyHeaderWord2 = ReadUint32(readBuffer, 16);
1242 const uint32_t bodyHeaderWord3 = ReadUint32(readBuffer, 20);
1243 const uint32_t bodyHeaderWord4 = ReadUint32(readBuffer, 24);
1244 const uint32_t bodyHeaderWord5 = ReadUint32(readBuffer, 28);
1245 const uint16_t deviceRecordCount = static_cast<uint16_t>(bodyHeaderWord0 >> 16);
1246 const uint16_t counterSetRecordCount = static_cast<uint16_t>(bodyHeaderWord2 >> 16);
1247 const uint16_t categoryRecordCount = static_cast<uint16_t>(bodyHeaderWord4 >> 16);
1248 BOOST_TEST(deviceRecordCount == 2); // device_records_count
1249 BOOST_TEST(bodyHeaderWord1 == bodyHeaderSize * 4); // device_records_pointer_table_offset
1250 BOOST_TEST(counterSetRecordCount == 1); // counter_set_count
1251 BOOST_TEST(bodyHeaderWord3 == 8 + bodyHeaderSize * 4); // counter_set_pointer_table_offset
1252 BOOST_TEST(categoryRecordCount == 2); // categories_count
1253 BOOST_TEST(bodyHeaderWord5 == 12 + bodyHeaderSize * 4); // categories_pointer_table_offset
1255 // Check the device records pointer table
1256 const uint32_t deviceRecordOffset0 = ReadUint32(readBuffer, 32);
1257 const uint32_t deviceRecordOffset1 = ReadUint32(readBuffer, 36);
1258 BOOST_TEST(deviceRecordOffset0 == 0); // Device record offset for "device1"
1259 BOOST_TEST(deviceRecordOffset1 == 20); // Device record offset for "device2"
1261 // Check the counter set pointer table
1262 const uint32_t counterSetRecordOffset0 = ReadUint32(readBuffer, 40);
1263 BOOST_TEST(counterSetRecordOffset0 == 40); // Counter set record offset for "counterset1"
1265 // Check the category pointer table
1266 const uint32_t categoryRecordOffset0 = ReadUint32(readBuffer, 44);
1267 const uint32_t categoryRecordOffset1 = ReadUint32(readBuffer, 48);
1268 BOOST_TEST(categoryRecordOffset0 == 64); // Category record offset for "category1"
1269 BOOST_TEST(categoryRecordOffset1 == 168); // Category record offset for "category2"
1271 // Get the device record pool offset
1272 const uint32_t uint32_t_size = sizeof(uint32_t);
1273 const uint32_t packetBodyPoolOffset = 2u * uint32_t_size + // packet_header
1274 bodyHeaderWord1 + // body_header
1275 deviceRecordCount * uint32_t_size + // Size of device_records_pointer_table
1276 counterSetRecordCount * uint32_t_size // Size of counter_set_pointer_table
1277 + categoryRecordCount * uint32_t_size; // Size of categories_pointer_table
1279 // Device record structure/collection used for testing
1284 uint32_t name_offset;
1285 uint32_t name_length;
1288 std::vector<DeviceRecord> deviceRecords;
1289 const uint32_t deviceRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
1290 bodyHeaderWord1; // device_records_pointer_table_offset
1292 const unsigned char* readData = readBuffer->GetReadableData();
1294 for (uint32_t i = 0; i < deviceRecordCount; i++)
1296 // Get the device record offset
1297 const uint32_t deviceRecordOffset = ReadUint32(readBuffer, deviceRecordsPointerTableOffset + i * uint32_t_size);
1299 // Collect the data for the device record
1300 const uint32_t deviceRecordWord0 = ReadUint32(readBuffer,
1301 packetBodyPoolOffset + deviceRecordOffset + 0 * uint32_t_size);
1302 const uint32_t deviceRecordWord1 = ReadUint32(readBuffer,
1303 packetBodyPoolOffset + deviceRecordOffset + 1 * uint32_t_size);
1304 DeviceRecord deviceRecord;
1305 deviceRecord.uid = static_cast<uint16_t>(deviceRecordWord0 >> 16); // uid
1306 deviceRecord.cores = static_cast<uint16_t>(deviceRecordWord0); // cores
1307 deviceRecord.name_offset = deviceRecordWord1; // name_offset
1309 uint32_t deviceRecordPoolOffset = packetBodyPoolOffset + // Packet body offset
1310 deviceRecordOffset + // Device record offset
1311 2 * uint32_t_size + // Device record header
1312 deviceRecord.name_offset; // Device name offset
1313 uint32_t deviceRecordNameLength = ReadUint32(readBuffer, deviceRecordPoolOffset);
1314 deviceRecord.name_length = deviceRecordNameLength; // name_length
1315 unsigned char deviceRecordNameNullTerminator = // name null-terminator
1316 ReadUint8(readBuffer, deviceRecordPoolOffset + uint32_t_size + deviceRecordNameLength - 1);
1317 BOOST_CHECK(deviceRecordNameNullTerminator == '\0');
1318 std::vector<unsigned char> deviceRecordNameBuffer(deviceRecord.name_length - 1);
1319 std::memcpy(deviceRecordNameBuffer.data(),
1320 readData + deviceRecordPoolOffset + uint32_t_size, deviceRecordNameBuffer.size());
1321 deviceRecord.name.assign(deviceRecordNameBuffer.begin(), deviceRecordNameBuffer.end()); // name
1323 deviceRecords.push_back(deviceRecord);
1326 // Check that the device records are correct
1327 BOOST_CHECK(deviceRecords.size() == 2);
1328 for (const DeviceRecord& deviceRecord : deviceRecords)
1330 const Device* device = counterDirectory.GetDevice(deviceRecord.uid);
1331 BOOST_CHECK(device);
1332 BOOST_CHECK(device->m_Uid == deviceRecord.uid);
1333 BOOST_CHECK(device->m_Cores == deviceRecord.cores);
1334 BOOST_CHECK(device->m_Name == deviceRecord.name);
1337 // Counter set record structure/collection used for testing
1338 struct CounterSetRecord
1342 uint32_t name_offset;
1343 uint32_t name_length;
1346 std::vector<CounterSetRecord> counterSetRecords;
1347 const uint32_t counterSetRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
1348 bodyHeaderWord3; // counter_set_pointer_table_offset
1349 for (uint32_t i = 0; i < counterSetRecordCount; i++)
1351 // Get the counter set record offset
1352 const uint32_t counterSetRecordOffset = ReadUint32(readBuffer,
1353 counterSetRecordsPointerTableOffset + i * uint32_t_size);
1355 // Collect the data for the counter set record
1356 const uint32_t counterSetRecordWord0 = ReadUint32(readBuffer,
1357 packetBodyPoolOffset + counterSetRecordOffset +
1359 const uint32_t counterSetRecordWord1 = ReadUint32(readBuffer,
1360 packetBodyPoolOffset + counterSetRecordOffset +
1362 CounterSetRecord counterSetRecord;
1363 counterSetRecord.uid = static_cast<uint16_t>(counterSetRecordWord0 >> 16); // uid
1364 counterSetRecord.count = static_cast<uint16_t>(counterSetRecordWord0); // count
1365 counterSetRecord.name_offset = counterSetRecordWord1; // name_offset
1367 uint32_t counterSetRecordPoolOffset = packetBodyPoolOffset + // Packet body offset
1368 counterSetRecordOffset + // Counter set record offset
1369 2 * uint32_t_size + // Counter set record header
1370 counterSetRecord.name_offset; // Counter set name offset
1371 uint32_t counterSetRecordNameLength = ReadUint32(readBuffer, counterSetRecordPoolOffset);
1372 counterSetRecord.name_length = counterSetRecordNameLength; // name_length
1373 unsigned char counterSetRecordNameNullTerminator = // name null-terminator
1374 ReadUint8(readBuffer, counterSetRecordPoolOffset + uint32_t_size + counterSetRecordNameLength - 1);
1375 BOOST_CHECK(counterSetRecordNameNullTerminator == '\0');
1376 std::vector<unsigned char> counterSetRecordNameBuffer(counterSetRecord.name_length - 1);
1377 std::memcpy(counterSetRecordNameBuffer.data(),
1378 readData + counterSetRecordPoolOffset + uint32_t_size, counterSetRecordNameBuffer.size());
1379 counterSetRecord.name.assign(counterSetRecordNameBuffer.begin(), counterSetRecordNameBuffer.end()); // name
1381 counterSetRecords.push_back(counterSetRecord);
1384 // Check that the counter set records are correct
1385 BOOST_CHECK(counterSetRecords.size() == 1);
1386 for (const CounterSetRecord& counterSetRecord : counterSetRecords)
1388 const CounterSet* counterSet = counterDirectory.GetCounterSet(counterSetRecord.uid);
1389 BOOST_CHECK(counterSet);
1390 BOOST_CHECK(counterSet->m_Uid == counterSetRecord.uid);
1391 BOOST_CHECK(counterSet->m_Count == counterSetRecord.count);
1392 BOOST_CHECK(counterSet->m_Name == counterSetRecord.name);
1395 // Event record structure/collection used for testing
1398 uint16_t counter_uid;
1399 uint16_t max_counter_uid;
1401 uint16_t counter_set;
1402 uint16_t counter_class;
1403 uint16_t interpolation;
1405 uint32_t name_offset;
1406 uint32_t name_length;
1408 uint32_t description_offset;
1409 uint32_t description_length;
1410 std::string description;
1411 uint32_t units_offset;
1412 uint32_t units_length;
1415 // Category record structure/collection used for testing
1416 struct CategoryRecord
1418 uint16_t event_count;
1419 uint32_t event_pointer_table_offset;
1420 uint32_t name_offset;
1421 uint32_t name_length;
1423 std::vector<uint32_t> event_pointer_table;
1424 std::vector<EventRecord> event_records;
1426 std::vector<CategoryRecord> categoryRecords;
1427 const uint32_t categoryRecordsPointerTableOffset = 2u * uint32_t_size + // packet_header
1428 bodyHeaderWord5; // categories_pointer_table_offset
1429 for (uint32_t i = 0; i < categoryRecordCount; i++)
1431 // Get the category record offset
1432 const uint32_t categoryRecordOffset = ReadUint32(readBuffer, categoryRecordsPointerTableOffset +
1435 // Collect the data for the category record
1436 const uint32_t categoryRecordWord1 = ReadUint32(readBuffer,
1437 packetBodyPoolOffset + categoryRecordOffset +
1439 const uint32_t categoryRecordWord2 = ReadUint32(readBuffer,
1440 packetBodyPoolOffset + categoryRecordOffset +
1442 const uint32_t categoryRecordWord3 = ReadUint32(readBuffer,
1443 packetBodyPoolOffset + categoryRecordOffset +
1445 CategoryRecord categoryRecord;
1446 categoryRecord.event_count = static_cast<uint16_t>(categoryRecordWord1 >> 16); // event_count
1447 categoryRecord.event_pointer_table_offset = categoryRecordWord2; // event_pointer_table_offset
1448 categoryRecord.name_offset = categoryRecordWord3; // name_offset
1450 uint32_t categoryRecordPoolOffset = packetBodyPoolOffset + // Packet body offset
1451 categoryRecordOffset + // Category record offset
1452 3 * uint32_t_size; // Category record header
1454 uint32_t categoryRecordNameLength = ReadUint32(readBuffer,
1455 categoryRecordPoolOffset + categoryRecord.name_offset);
1456 categoryRecord.name_length = categoryRecordNameLength; // name_length
1457 unsigned char categoryRecordNameNullTerminator =
1458 ReadUint8(readBuffer,
1459 categoryRecordPoolOffset +
1460 categoryRecord.name_offset +
1462 categoryRecordNameLength - 1); // name null-terminator
1463 BOOST_CHECK(categoryRecordNameNullTerminator == '\0');
1464 std::vector<unsigned char> categoryRecordNameBuffer(categoryRecord.name_length - 1);
1465 std::memcpy(categoryRecordNameBuffer.data(),
1467 categoryRecordPoolOffset +
1468 categoryRecord.name_offset +
1470 categoryRecordNameBuffer.size());
1471 categoryRecord.name.assign(categoryRecordNameBuffer.begin(), categoryRecordNameBuffer.end()); // name
1473 categoryRecord.event_pointer_table.resize(categoryRecord.event_count);
1474 for (uint32_t eventIndex = 0; eventIndex < categoryRecord.event_count; eventIndex++)
1476 uint32_t eventRecordOffset = ReadUint32(readBuffer,
1477 categoryRecordPoolOffset +
1478 categoryRecord.event_pointer_table_offset +
1479 eventIndex * uint32_t_size);
1480 categoryRecord.event_pointer_table[eventIndex] = eventRecordOffset;
1482 // Collect the data for the event record
1483 const uint32_t eventRecordWord0 = ReadUint32(readBuffer,
1484 categoryRecordPoolOffset + eventRecordOffset +
1486 const uint32_t eventRecordWord1 = ReadUint32(readBuffer,
1487 categoryRecordPoolOffset + eventRecordOffset +
1489 const uint32_t eventRecordWord2 = ReadUint32(readBuffer,
1490 categoryRecordPoolOffset + eventRecordOffset +
1492 const uint64_t eventRecordWord34 = ReadUint64(readBuffer,
1493 categoryRecordPoolOffset + eventRecordOffset +
1495 const uint32_t eventRecordWord5 = ReadUint32(readBuffer,
1496 categoryRecordPoolOffset + eventRecordOffset +
1498 const uint32_t eventRecordWord6 = ReadUint32(readBuffer,
1499 categoryRecordPoolOffset + eventRecordOffset +
1501 const uint32_t eventRecordWord7 = ReadUint32(readBuffer,
1502 categoryRecordPoolOffset + eventRecordOffset +
1504 EventRecord eventRecord;
1505 eventRecord.counter_uid = static_cast<uint16_t>(eventRecordWord0); // counter_uid
1506 eventRecord.max_counter_uid = static_cast<uint16_t>(eventRecordWord0 >> 16); // max_counter_uid
1507 eventRecord.device = static_cast<uint16_t>(eventRecordWord1 >> 16); // device
1508 eventRecord.counter_set = static_cast<uint16_t>(eventRecordWord1); // counter_set
1509 eventRecord.counter_class = static_cast<uint16_t>(eventRecordWord2 >> 16); // class
1510 eventRecord.interpolation = static_cast<uint16_t>(eventRecordWord2); // interpolation
1511 std::memcpy(&eventRecord.multiplier, &eventRecordWord34, sizeof(eventRecord.multiplier)); // multiplier
1512 eventRecord.name_offset = static_cast<uint32_t>(eventRecordWord5); // name_offset
1513 eventRecord.description_offset = static_cast<uint32_t>(eventRecordWord6); // description_offset
1514 eventRecord.units_offset = static_cast<uint32_t>(eventRecordWord7); // units_offset
1516 uint32_t eventRecordPoolOffset = categoryRecordPoolOffset + // Category record pool offset
1517 eventRecordOffset + // Event record offset
1518 8 * uint32_t_size; // Event record header
1520 uint32_t eventRecordNameLength = ReadUint32(readBuffer,
1521 eventRecordPoolOffset + eventRecord.name_offset);
1522 eventRecord.name_length = eventRecordNameLength; // name_length
1523 unsigned char eventRecordNameNullTerminator =
1524 ReadUint8(readBuffer,
1525 eventRecordPoolOffset +
1526 eventRecord.name_offset +
1528 eventRecordNameLength - 1); // name null-terminator
1529 BOOST_CHECK(eventRecordNameNullTerminator == '\0');
1530 std::vector<unsigned char> eventRecordNameBuffer(eventRecord.name_length - 1);
1531 std::memcpy(eventRecordNameBuffer.data(),
1533 eventRecordPoolOffset +
1534 eventRecord.name_offset +
1536 eventRecordNameBuffer.size());
1537 eventRecord.name.assign(eventRecordNameBuffer.begin(), eventRecordNameBuffer.end()); // name
1539 uint32_t eventRecordDescriptionLength = ReadUint32(readBuffer,
1540 eventRecordPoolOffset + eventRecord.description_offset);
1541 eventRecord.description_length = eventRecordDescriptionLength; // description_length
1542 unsigned char eventRecordDescriptionNullTerminator =
1543 ReadUint8(readBuffer,
1544 eventRecordPoolOffset +
1545 eventRecord.description_offset +
1547 eventRecordDescriptionLength - 1); // description null-terminator
1548 BOOST_CHECK(eventRecordDescriptionNullTerminator == '\0');
1549 std::vector<unsigned char> eventRecordDescriptionBuffer(eventRecord.description_length - 1);
1550 std::memcpy(eventRecordDescriptionBuffer.data(),
1552 eventRecordPoolOffset +
1553 eventRecord.description_offset +
1555 eventRecordDescriptionBuffer.size());
1556 eventRecord.description.assign(eventRecordDescriptionBuffer.begin(),
1557 eventRecordDescriptionBuffer.end()); // description
1559 if (eventRecord.units_offset > 0)
1561 uint32_t eventRecordUnitsLength = ReadUint32(readBuffer,
1562 eventRecordPoolOffset + eventRecord.units_offset);
1563 eventRecord.units_length = eventRecordUnitsLength; // units_length
1564 unsigned char eventRecordUnitsNullTerminator =
1565 ReadUint8(readBuffer,
1566 eventRecordPoolOffset +
1567 eventRecord.units_offset +
1569 eventRecordUnitsLength - 1); // units null-terminator
1570 BOOST_CHECK(eventRecordUnitsNullTerminator == '\0');
1571 std::vector<unsigned char> eventRecordUnitsBuffer(eventRecord.units_length - 1);
1572 std::memcpy(eventRecordUnitsBuffer.data(),
1574 eventRecordPoolOffset +
1575 eventRecord.units_offset +
1577 eventRecordUnitsBuffer.size());
1578 eventRecord.units.assign(eventRecordUnitsBuffer.begin(), eventRecordUnitsBuffer.end()); // units
1581 categoryRecord.event_records.push_back(eventRecord);
1584 categoryRecords.push_back(categoryRecord);
1587 // Check that the category records are correct
1588 BOOST_CHECK(categoryRecords.size() == 2);
1589 for (const CategoryRecord& categoryRecord : categoryRecords)
1591 const Category* category = counterDirectory.GetCategory(categoryRecord.name);
1592 BOOST_CHECK(category);
1593 BOOST_CHECK(category->m_Name == categoryRecord.name);
1594 BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
1595 BOOST_CHECK(category->m_Counters.size() == categoryRecord.event_count + static_cast<size_t>(numberOfCores) -1);
1597 // Check that the event records are correct
1598 for (const EventRecord& eventRecord : categoryRecord.event_records)
1600 const Counter* counter = counterDirectory.GetCounter(eventRecord.counter_uid);
1601 BOOST_CHECK(counter);
1602 BOOST_CHECK(counter->m_MaxCounterUid == eventRecord.max_counter_uid);
1603 BOOST_CHECK(counter->m_DeviceUid == eventRecord.device);
1604 BOOST_CHECK(counter->m_CounterSetUid == eventRecord.counter_set);
1605 BOOST_CHECK(counter->m_Class == eventRecord.counter_class);
1606 BOOST_CHECK(counter->m_Interpolation == eventRecord.interpolation);
1607 BOOST_CHECK(counter->m_Multiplier == eventRecord.multiplier);
1608 BOOST_CHECK(counter->m_Name == eventRecord.name);
1609 BOOST_CHECK(counter->m_Description == eventRecord.description);
1610 BOOST_CHECK(counter->m_Units == eventRecord.units);
1615 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest3)
1617 // Using a mock counter directory that allows to register invalid objects
1618 MockCounterDirectory counterDirectory;
1620 // Register an invalid device
1621 const std::string deviceName = "inv@lid dev!c€";
1622 const Device* device = nullptr;
1623 BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1624 BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1625 BOOST_CHECK(device);
1627 // Buffer with enough space
1628 MockBufferManager mockBuffer(1024);
1629 SendCounterPacket sendCounterPacket(mockBuffer);
1630 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1633 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest4)
1635 // Using a mock counter directory that allows to register invalid objects
1636 MockCounterDirectory counterDirectory;
1638 // Register an invalid counter set
1639 const std::string counterSetName = "inv@lid count€rs€t";
1640 const CounterSet* counterSet = nullptr;
1641 BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1642 BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1643 BOOST_CHECK(counterSet);
1645 // Buffer with enough space
1646 MockBufferManager mockBuffer(1024);
1647 SendCounterPacket sendCounterPacket(mockBuffer);
1648 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1651 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest5)
1653 // Using a mock counter directory that allows to register invalid objects
1654 MockCounterDirectory counterDirectory;
1656 // Register an invalid category
1657 const std::string categoryName = "c@t€gory";
1658 const Category* category = nullptr;
1659 BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1660 BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1661 BOOST_CHECK(category);
1663 // Buffer with enough space
1664 MockBufferManager mockBuffer(1024);
1665 SendCounterPacket sendCounterPacket(mockBuffer);
1666 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1669 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest6)
1671 // Using a mock counter directory that allows to register invalid objects
1672 MockCounterDirectory counterDirectory;
1674 // Register an invalid device
1675 const std::string deviceName = "inv@lid dev!c€";
1676 const Device* device = nullptr;
1677 BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1678 BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1679 BOOST_CHECK(device);
1681 // Register an invalid counter set
1682 const std::string counterSetName = "inv@lid count€rs€t";
1683 const CounterSet* counterSet = nullptr;
1684 BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1685 BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1686 BOOST_CHECK(counterSet);
1688 // Register an invalid category associated to an invalid device and an invalid counter set
1689 const std::string categoryName = "c@t€gory";
1690 const Category* category = nullptr;
1691 BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1692 BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1693 BOOST_CHECK(category);
1695 // Buffer with enough space
1696 MockBufferManager mockBuffer(1024);
1697 SendCounterPacket sendCounterPacket(mockBuffer);
1698 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1701 BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest7)
1703 // Using a mock counter directory that allows to register invalid objects
1704 MockCounterDirectory counterDirectory;
1706 // Register an valid device
1707 const std::string deviceName = "valid device";
1708 const Device* device = nullptr;
1709 BOOST_CHECK_NO_THROW(device = counterDirectory.RegisterDevice(deviceName, 3));
1710 BOOST_CHECK(counterDirectory.GetDeviceCount() == 1);
1711 BOOST_CHECK(device);
1713 // Register an valid counter set
1714 const std::string counterSetName = "valid counterset";
1715 const CounterSet* counterSet = nullptr;
1716 BOOST_CHECK_NO_THROW(counterSet = counterDirectory.RegisterCounterSet(counterSetName));
1717 BOOST_CHECK(counterDirectory.GetCounterSetCount() == 1);
1718 BOOST_CHECK(counterSet);
1720 // Register an valid category associated to a valid device and a valid counter set
1721 const std::string categoryName = "category";
1722 const Category* category = nullptr;
1723 BOOST_CHECK_NO_THROW(category = counterDirectory.RegisterCategory(categoryName));
1724 BOOST_CHECK(counterDirectory.GetCategoryCount() == 1);
1725 BOOST_CHECK(category);
1727 // Register an invalid counter associated to a valid category
1728 const Counter* counter = nullptr;
1729 BOOST_CHECK_NO_THROW(counter = counterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
1736 "counter description",
1737 std::string("invalid counter units"),
1740 counterSet->m_Uid));
1741 BOOST_CHECK(counterDirectory.GetCounterCount() == 5);
1742 BOOST_CHECK(counter);
1744 // Buffer with enough space
1745 MockBufferManager mockBuffer(1024);
1746 SendCounterPacket sendCounterPacket(mockBuffer);
1747 BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException);
1750 BOOST_AUTO_TEST_CASE(SendThreadTest0)
1752 ProfilingStateMachine profilingStateMachine;
1753 SetActiveProfilingState(profilingStateMachine);
1755 MockProfilingConnection mockProfilingConnection;
1756 MockStreamCounterBuffer mockStreamCounterBuffer(0);
1757 SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1758 SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1760 // Try to start the send thread many times, it must only start once
1762 sendThread.Start(mockProfilingConnection);
1763 BOOST_CHECK(sendThread.IsRunning());
1764 sendThread.Start(mockProfilingConnection);
1765 sendThread.Start(mockProfilingConnection);
1766 sendThread.Start(mockProfilingConnection);
1767 sendThread.Start(mockProfilingConnection);
1768 BOOST_CHECK(sendThread.IsRunning());
1771 BOOST_CHECK(!sendThread.IsRunning());
1774 BOOST_AUTO_TEST_CASE(SendThreadTest1)
1776 ProfilingStateMachine profilingStateMachine;
1777 SetActiveProfilingState(profilingStateMachine);
1779 unsigned int totalWrittenSize = 0;
1781 MockProfilingConnection mockProfilingConnection;
1782 MockStreamCounterBuffer mockStreamCounterBuffer(1024);
1783 SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1784 SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1785 sendThread.Start(mockProfilingConnection);
1787 // Interleaving writes and reads to/from the buffer with pauses to test that the send thread actually waits for
1788 // something to become available for reading
1790 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1792 CounterDirectory counterDirectory;
1793 sendCounterPacket.SendStreamMetaDataPacket();
1795 totalWrittenSize += GetStreamMetaDataPacketSize();
1797 sendThread.SetReadyToRead();
1799 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1801 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
1803 // Get the size of the Counter Directory Packet
1804 unsigned int counterDirectoryPacketSize = 32;
1805 totalWrittenSize += counterDirectoryPacketSize;
1807 sendThread.SetReadyToRead();
1809 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1811 sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
1817 // Get the size of the Periodic Counter Capture Packet
1818 unsigned int periodicCounterCapturePacketSize = 28;
1819 totalWrittenSize += periodicCounterCapturePacketSize;
1821 sendThread.SetReadyToRead();
1823 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1825 sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
1830 // Get the size of the Periodic Counter Capture Packet
1831 periodicCounterCapturePacketSize = 22;
1832 totalWrittenSize += periodicCounterCapturePacketSize;
1834 sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
1843 // Get the size of the Periodic Counter Capture Packet
1844 periodicCounterCapturePacketSize = 46;
1845 totalWrittenSize += periodicCounterCapturePacketSize;
1847 sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
1855 // Get the size of the Periodic Counter Capture Packet
1856 periodicCounterCapturePacketSize = 40;
1857 totalWrittenSize += periodicCounterCapturePacketSize;
1859 sendThread.SetReadyToRead();
1861 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1863 sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
1865 // Get the size of the Periodic Counter Capture Packet
1866 periodicCounterCapturePacketSize = 30;
1867 totalWrittenSize += periodicCounterCapturePacketSize;
1869 sendThread.SetReadyToRead();
1871 // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
1872 // read all what's remaining in the buffer
1873 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1877 BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
1878 BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
1879 BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
1882 BOOST_AUTO_TEST_CASE(SendThreadTest2)
1884 ProfilingStateMachine profilingStateMachine;
1885 SetActiveProfilingState(profilingStateMachine);
1887 unsigned int totalWrittenSize = 0;
1889 MockProfilingConnection mockProfilingConnection;
1890 MockStreamCounterBuffer mockStreamCounterBuffer(1024);
1891 SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
1892 SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
1893 sendThread.Start(mockProfilingConnection);
1895 // Adding many spurious "ready to read" signals throughout the test to check that the send thread is
1896 // capable of handling unnecessary read requests
1898 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1900 sendThread.SetReadyToRead();
1902 CounterDirectory counterDirectory;
1903 sendCounterPacket.SendStreamMetaDataPacket();
1905 totalWrittenSize += GetStreamMetaDataPacketSize();
1907 sendThread.SetReadyToRead();
1909 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1911 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
1913 // Get the size of the Counter Directory Packet
1914 unsigned int counterDirectoryPacketSize = 32;
1915 totalWrittenSize += counterDirectoryPacketSize;
1917 sendThread.SetReadyToRead();
1918 sendThread.SetReadyToRead();
1920 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1922 sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
1928 // Get the size of the Periodic Counter Capture Packet
1929 unsigned int periodicCounterCapturePacketSize = 28;
1930 totalWrittenSize += periodicCounterCapturePacketSize;
1932 sendThread.SetReadyToRead();
1934 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1936 sendThread.SetReadyToRead();
1937 sendThread.SetReadyToRead();
1938 sendThread.SetReadyToRead();
1940 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1942 sendThread.SetReadyToRead();
1943 sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
1948 // Get the size of the Periodic Counter Capture Packet
1949 periodicCounterCapturePacketSize = 22;
1950 totalWrittenSize += periodicCounterCapturePacketSize;
1952 sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
1961 // Get the size of the Periodic Counter Capture Packet
1962 periodicCounterCapturePacketSize = 46;
1963 totalWrittenSize += periodicCounterCapturePacketSize;
1965 sendThread.SetReadyToRead();
1966 sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
1974 // Get the size of the Periodic Counter Capture Packet
1975 periodicCounterCapturePacketSize = 40;
1976 totalWrittenSize += periodicCounterCapturePacketSize;
1978 sendThread.SetReadyToRead();
1979 sendThread.SetReadyToRead();
1981 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_UNTIL_READABLE_MS));
1983 sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
1985 // Get the size of the Periodic Counter Capture Packet
1986 periodicCounterCapturePacketSize = 30;
1987 totalWrittenSize += periodicCounterCapturePacketSize;
1989 sendThread.SetReadyToRead();
1991 // To test an exact value of the "read size" in the mock buffer, wait to allow the send thread to
1992 // read all what's remaining in the buffer
1995 BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
1996 BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() == totalWrittenSize);
1997 BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize);
2000 BOOST_AUTO_TEST_CASE(SendThreadTest3)
2002 ProfilingStateMachine profilingStateMachine;
2003 SetActiveProfilingState(profilingStateMachine);
2005 unsigned int totalWrittenSize = 0;
2007 MockProfilingConnection mockProfilingConnection;
2008 MockStreamCounterBuffer mockStreamCounterBuffer(1024);
2009 SendCounterPacket sendCounterPacket(mockStreamCounterBuffer);
2010 SendThread sendThread(profilingStateMachine, mockStreamCounterBuffer, sendCounterPacket);
2011 sendThread.Start(mockProfilingConnection);
2013 // Not using pauses or "grace periods" to stress test the send thread
2015 sendThread.SetReadyToRead();
2017 CounterDirectory counterDirectory;
2018 sendCounterPacket.SendStreamMetaDataPacket();
2020 totalWrittenSize += GetStreamMetaDataPacketSize();
2022 sendThread.SetReadyToRead();
2023 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2025 // Get the size of the Counter Directory Packet
2026 unsigned int counterDirectoryPacketSize =32;
2027 totalWrittenSize += counterDirectoryPacketSize;
2029 sendThread.SetReadyToRead();
2030 sendThread.SetReadyToRead();
2031 sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2037 // Get the size of the Periodic Counter Capture Packet
2038 unsigned int periodicCounterCapturePacketSize = 28;
2039 totalWrittenSize += periodicCounterCapturePacketSize;
2041 sendThread.SetReadyToRead();
2042 sendThread.SetReadyToRead();
2043 sendThread.SetReadyToRead();
2044 sendThread.SetReadyToRead();
2045 sendThread.SetReadyToRead();
2046 sendCounterPacket.SendPeriodicCounterCapturePacket(44u,
2051 // Get the size of the Periodic Counter Capture Packet
2052 periodicCounterCapturePacketSize = 22;
2053 totalWrittenSize += periodicCounterCapturePacketSize;
2055 sendCounterPacket.SendPeriodicCounterCapturePacket(1234u,
2064 // Get the size of the Periodic Counter Capture Packet
2065 periodicCounterCapturePacketSize = 46;
2066 totalWrittenSize += periodicCounterCapturePacketSize;
2068 sendThread.SetReadyToRead();
2069 sendThread.SetReadyToRead();
2070 sendCounterPacket.SendPeriodicCounterCapturePacket(997u,
2078 // Get the size of the Periodic Counter Capture Packet
2079 periodicCounterCapturePacketSize = 40;
2080 totalWrittenSize += periodicCounterCapturePacketSize;
2082 sendThread.SetReadyToRead();
2083 sendThread.SetReadyToRead();
2084 sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u });
2086 // Get the size of the Periodic Counter Capture Packet
2087 periodicCounterCapturePacketSize = 30;
2088 totalWrittenSize += periodicCounterCapturePacketSize;
2090 sendThread.SetReadyToRead();
2092 // Abruptly terminating the send thread, the amount of data sent may be less that the amount written (the send
2093 // thread is not guaranteed to flush the buffer)
2096 BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize);
2097 BOOST_CHECK(mockStreamCounterBuffer.GetReadableSize() <= totalWrittenSize);
2098 BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= totalWrittenSize);
2099 BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetReadableSize());
2100 BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= mockStreamCounterBuffer.GetCommittedSize());
2103 BOOST_AUTO_TEST_CASE(SendCounterPacketTestWithSendThread)
2105 ProfilingStateMachine profilingStateMachine;
2106 SetWaitingForAckProfilingState(profilingStateMachine);
2108 MockProfilingConnection mockProfilingConnection;
2109 BufferManager bufferManager(1, 1024);
2110 SendCounterPacket sendCounterPacket(bufferManager);
2111 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
2112 sendThread.Start(mockProfilingConnection);
2114 unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2118 // check for packet in ProfilingConnection
2119 BOOST_CHECK(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) == 1);
2121 SetActiveProfilingState(profilingStateMachine);
2122 sendThread.Start(mockProfilingConnection);
2124 // SendCounterDirectoryPacket
2125 CounterDirectory counterDirectory;
2126 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2129 unsigned int counterDirectoryPacketSize = 32;
2130 // check for packet in ProfilingConnection
2131 BOOST_CHECK(mockProfilingConnection.CheckForPacket(
2132 {PacketType::CounterDirectory, counterDirectoryPacketSize}) == 1);
2134 sendThread.Start(mockProfilingConnection);
2136 // SendPeriodicCounterCapturePacket
2137 sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2145 unsigned int periodicCounterCapturePacketSize = 28;
2146 BOOST_CHECK(mockProfilingConnection.CheckForPacket(
2147 {PacketType::PeriodicCounterCapture, periodicCounterCapturePacketSize}) == 1);
2150 BOOST_AUTO_TEST_CASE(SendThreadBufferTest)
2152 ProfilingStateMachine profilingStateMachine;
2153 SetActiveProfilingState(profilingStateMachine);
2155 MockProfilingConnection mockProfilingConnection;
2156 BufferManager bufferManager(3, 1024);
2157 SendCounterPacket sendCounterPacket(bufferManager);
2158 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket, -1);
2159 sendThread.Start(mockProfilingConnection);
2161 // SendStreamMetaDataPacket
2162 sendCounterPacket.SendStreamMetaDataPacket();
2164 // Read data from the buffer
2165 // Buffer should become readable after commit by SendStreamMetaDataPacket
2166 auto packetBuffer = bufferManager.GetReadableBuffer();
2167 BOOST_TEST(packetBuffer.get());
2169 unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2170 BOOST_TEST(packetBuffer->GetSize() == streamMetadataPacketsize);
2172 // Recommit to be read by sendCounterPacket
2173 bufferManager.Commit(packetBuffer, streamMetadataPacketsize);
2175 // SendCounterDirectoryPacket
2176 CounterDirectory counterDirectory;
2177 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
2179 // SendPeriodicCounterCapturePacket
2180 sendCounterPacket.SendPeriodicCounterCapturePacket(123u,
2188 // The buffer is read by the send thread so it should not be in the readable buffer.
2189 auto readBuffer = bufferManager.GetReadableBuffer();
2190 BOOST_TEST(!readBuffer);
2192 // Successfully reserved the buffer with requested size
2193 unsigned int reservedSize = 0;
2194 auto reservedBuffer = bufferManager.Reserve(512, reservedSize);
2195 BOOST_TEST(reservedSize == 512);
2196 BOOST_TEST(reservedBuffer.get());
2198 const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2199 const auto metaDataPacketCount =
2200 mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize});
2202 BOOST_TEST(metaDataPacketCount >= 1);
2203 BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::CounterDirectory, 32}) == 1);
2204 BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::PeriodicCounterCapture, 28}) == 1);
2205 // Check that we only received the packets we expected
2206 BOOST_TEST(metaDataPacketCount + 2 == writtenDataSize);
2209 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket1)
2211 ProfilingStateMachine profilingStateMachine;
2213 MockProfilingConnection mockProfilingConnection;
2214 BufferManager bufferManager(3, 1024);
2215 SendCounterPacket sendCounterPacket(bufferManager);
2216 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2217 sendThread.Start(mockProfilingConnection);
2219 // The profiling state is set to "Uninitialized", so the send thread should throw an exception
2220 BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
2223 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket2)
2225 ProfilingStateMachine profilingStateMachine;
2226 SetNotConnectedProfilingState(profilingStateMachine);
2228 MockProfilingConnection mockProfilingConnection;
2229 BufferManager bufferManager(3, 1024);
2230 SendCounterPacket sendCounterPacket(bufferManager);
2231 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2232 sendThread.Start(mockProfilingConnection);
2234 // The profiling state is set to "NotConnected", so the send thread should throw an exception
2235 BOOST_CHECK_THROW(sendThread.Stop(), armnn::RuntimeException);
2238 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket3)
2240 ProfilingStateMachine profilingStateMachine;
2241 SetWaitingForAckProfilingState(profilingStateMachine);
2243 unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2245 MockProfilingConnection mockProfilingConnection;
2246 BufferManager bufferManager(3, 1024);
2247 SendCounterPacket sendCounterPacket(bufferManager);
2248 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2249 sendThread.Start(mockProfilingConnection);
2251 // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
2252 // Wait for sendThread to join
2253 BOOST_CHECK_NO_THROW(sendThread.Stop());
2255 // Check that the buffer contains at least one Stream Metadata packet and no other packets
2256 const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2258 BOOST_TEST(writtenDataSize >= 1);
2259 BOOST_TEST(mockProfilingConnection.CheckForPacket(
2260 {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
2263 BOOST_AUTO_TEST_CASE(SendThreadSendStreamMetadataPacket4)
2265 ProfilingStateMachine profilingStateMachine;
2266 SetWaitingForAckProfilingState(profilingStateMachine);
2268 unsigned int streamMetadataPacketsize = GetStreamMetaDataPacketSize();
2270 MockProfilingConnection mockProfilingConnection;
2271 BufferManager bufferManager(3, 1024);
2272 SendCounterPacket sendCounterPacket(bufferManager);
2273 SendThread sendThread(profilingStateMachine, bufferManager, sendCounterPacket);
2274 sendThread.Start(mockProfilingConnection);
2276 // The profiling state is set to "WaitingForAck", so the send thread should send a Stream Metadata packet
2277 // Wait for sendThread to join
2280 sendThread.Start(mockProfilingConnection);
2281 // Check that the profiling state is still "WaitingForAck"
2282 BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
2284 // Check that the buffer contains at least one Stream Metadata packet
2285 BOOST_TEST(mockProfilingConnection.CheckForPacket({PacketType::StreamMetaData, streamMetadataPacketsize}) >= 1);
2287 mockProfilingConnection.Clear();
2290 sendThread.Start(mockProfilingConnection);
2292 // Try triggering a new buffer read
2293 sendThread.SetReadyToRead();
2295 // Wait for sendThread to join
2296 BOOST_CHECK_NO_THROW(sendThread.Stop());
2298 // Check that the profiling state is still "WaitingForAck"
2299 BOOST_TEST((profilingStateMachine.GetCurrentState() == ProfilingState::WaitingForAck));
2301 // Check that the buffer contains at least one Stream Metadata packet and no other packets
2302 const auto writtenDataSize = mockProfilingConnection.GetWrittenDataSize();
2304 BOOST_TEST(writtenDataSize >= 1);
2305 BOOST_TEST(mockProfilingConnection.CheckForPacket(
2306 {PacketType::StreamMetaData, streamMetadataPacketsize}) == writtenDataSize);
2309 BOOST_AUTO_TEST_SUITE_END()