2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "../SendCounterPacket.hpp"
7 #include "../ProfilingUtils.hpp"
8 #include "../EncodeVersion.hpp"
10 #include <armnn/Exceptions.hpp>
12 #include <boost/test/unit_test.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
18 BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
20 using namespace armnn::profiling;
22 class MockBuffer : public IBufferWrapper
25 MockBuffer(unsigned int size)
27 m_Buffer(std::make_unique<unsigned char[]>(size)) {}
29 unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
31 if (requestedSize > m_BufferSize)
33 reservedSize = m_BufferSize;
37 reservedSize = requestedSize;
40 return m_Buffer.get();
43 void Commit(unsigned int size) override {}
45 const unsigned char* GetReadBuffer(unsigned int& size) override
47 size = static_cast<unsigned int>(strlen(reinterpret_cast<const char*>(m_Buffer.get())) + 1);
48 return m_Buffer.get();
51 void Release( unsigned int size) override {}
54 unsigned int m_BufferSize;
55 std::unique_ptr<unsigned char[]> m_Buffer;
58 class MockSendCounterPacket : public ISendCounterPacket
61 MockSendCounterPacket(IBufferWrapper& sendBuffer) : m_Buffer(sendBuffer) {}
63 void SendStreamMetaDataPacket() override
65 std::string message("SendStreamMetaDataPacket");
66 unsigned int reserved = 0;
67 unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
68 memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
71 void SendCounterDirectoryPacket(const Category& category, const std::vector<Counter>& counters) override
73 std::string message("SendCounterDirectoryPacket");
74 unsigned int reserved = 0;
75 unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
76 memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
79 void SendPeriodicCounterCapturePacket(uint64_t timestamp,
80 const std::vector<std::pair<uint16_t, uint32_t>>& values) override
82 std::string message("SendPeriodicCounterCapturePacket");
83 unsigned int reserved = 0;
84 unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
85 memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
88 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
89 const std::vector<uint16_t>& selectedCounterIds) override
91 std::string message("SendPeriodicCounterSelectionPacket");
92 unsigned int reserved = 0;
93 unsigned char* buffer = m_Buffer.Reserve(1024, reserved);
94 memcpy(buffer, message.c_str(), static_cast<unsigned int>(message.size()) + 1);
95 m_Buffer.Commit(reserved);
98 void SetReadyToRead() override
102 IBufferWrapper& m_Buffer;
105 BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
107 unsigned int size = 0;
109 MockBuffer mockBuffer(512);
110 MockSendCounterPacket sendCounterPacket(mockBuffer);
112 sendCounterPacket.SendStreamMetaDataPacket();
113 const char* buffer = reinterpret_cast<const char*>(mockBuffer.GetReadBuffer(size));
115 BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
118 std::vector<Counter> counters;
119 sendCounterPacket.SendCounterDirectoryPacket(category, counters);
121 BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
123 uint64_t timestamp = 0;
124 std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
126 sendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
128 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
130 uint32_t capturePeriod = 0;
131 std::vector<uint16_t> selectedCounterIds;
132 sendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
134 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
138 BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest)
140 // Error no space left in buffer
141 MockBuffer mockBuffer1(10);
142 SendCounterPacket sendPacket1(mockBuffer1);
144 uint32_t capturePeriod = 1000;
145 std::vector<uint16_t> selectedCounterIds;
146 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
147 armnn::RuntimeException);
149 // Packet without any counters
150 MockBuffer mockBuffer2(512);
151 SendCounterPacket sendPacket2(mockBuffer2);
153 sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
154 unsigned int sizeRead = 0;
155 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
157 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
158 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
159 uint32_t period = ReadUint32(readBuffer2, 8);
161 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
162 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
163 BOOST_TEST(headerWord1 == 4); // data lenght
164 BOOST_TEST(period == 1000); // capture period
166 // Full packet message
167 MockBuffer mockBuffer3(512);
168 SendCounterPacket sendPacket3(mockBuffer3);
170 selectedCounterIds.reserve(5);
171 selectedCounterIds.emplace_back(100);
172 selectedCounterIds.emplace_back(200);
173 selectedCounterIds.emplace_back(300);
174 selectedCounterIds.emplace_back(400);
175 selectedCounterIds.emplace_back(500);
176 sendPacket3.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
178 const unsigned char* readBuffer3 = mockBuffer3.GetReadBuffer(sizeRead);
180 headerWord0 = ReadUint32(readBuffer3, 0);
181 headerWord1 = ReadUint32(readBuffer3, 4);
182 period = ReadUint32(readBuffer3, 8);
184 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
185 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
186 BOOST_TEST(headerWord1 == 14); // data lenght
187 BOOST_TEST(period == 1000); // capture period
189 uint16_t counterId = 0;
190 uint32_t offset = 12;
193 for(const uint16_t& id : selectedCounterIds)
195 counterId = ReadUint16(readBuffer3, offset);
196 BOOST_TEST(counterId == id);
201 BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest)
203 // Error no space left in buffer
204 MockBuffer mockBuffer1(10);
205 SendCounterPacket sendPacket1(mockBuffer1);
207 auto captureTimestamp = std::chrono::steady_clock::now();
208 uint64_t time = static_cast<uint64_t >(captureTimestamp.time_since_epoch().count());
209 std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
211 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterCapturePacket(time, indexValuePairs),
214 // Packet without any counters
215 MockBuffer mockBuffer2(512);
216 SendCounterPacket sendPacket2(mockBuffer2);
218 sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs);
219 unsigned int sizeRead = 0;
220 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
222 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
223 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
224 uint64_t readTimestamp = ReadUint64(readBuffer2, 8);
226 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 1); // packet family
227 BOOST_TEST(((headerWord0 >> 19) & 0x3F) == 0); // packet class
228 BOOST_TEST(((headerWord0 >> 16) & 0x3) == 0); // packet type
229 BOOST_TEST(headerWord1 == 8); // data length
230 BOOST_TEST(time == readTimestamp); // capture period
232 // Full packet message
233 MockBuffer mockBuffer3(512);
234 SendCounterPacket sendPacket3(mockBuffer3);
236 indexValuePairs.reserve(5);
237 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(0, 100));
238 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(1, 200));
239 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(2, 300));
240 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(3, 400));
241 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(4, 500));
242 sendPacket3.SendPeriodicCounterCapturePacket(time, indexValuePairs);
244 const unsigned char* readBuffer3 = mockBuffer3.GetReadBuffer(sizeRead);
246 headerWord0 = ReadUint32(readBuffer3, 0);
247 headerWord1 = ReadUint32(readBuffer3, 4);
248 uint64_t readTimestamp2 = ReadUint64(readBuffer3, 8);
250 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 1); // packet family
251 BOOST_TEST(((headerWord0 >> 19) & 0x3F) == 0); // packet class
252 BOOST_TEST(((headerWord0 >> 16) & 0x3) == 0); // packet type
253 BOOST_TEST(headerWord1 == 38); // data length
254 BOOST_TEST(time == readTimestamp2); // capture period
256 uint16_t counterIndex = 0;
257 uint32_t counterValue = 100;
258 uint32_t offset = 16;
261 for (auto it = indexValuePairs.begin(), end = indexValuePairs.end(); it != end; ++it)
263 // Check Counter Index
264 uint16_t readIndex = ReadUint16(readBuffer3, offset);
265 BOOST_TEST(counterIndex == readIndex);
269 // Check Counter Value
270 uint32_t readValue = ReadUint32(readBuffer3, offset);
271 BOOST_TEST(counterValue == readValue);
278 BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
280 using boost::numeric_cast;
282 uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
284 // Error no space left in buffer
285 MockBuffer mockBuffer1(10);
286 SendCounterPacket sendPacket1(mockBuffer1);
287 BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::RuntimeException);
289 // Full metadata packet
291 std::string processName = GetProcessName().substr(0, 60);
293 uint32_t infoSize = numeric_cast<uint32_t>(GetSoftwareInfo().size()) > 0 ?
294 numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1 : 0;
295 uint32_t hardwareVersionSize = numeric_cast<uint32_t>(GetHardwareVersion().size()) > 0 ?
296 numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1 : 0;
297 uint32_t softwareVersionSize = numeric_cast<uint32_t>(GetSoftwareVersion().size()) > 0 ?
298 numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1 : 0;
299 uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) > 0 ?
300 numeric_cast<uint32_t>(processName.size()) + 1 : 0;
302 uint32_t packetEntries = 5;
304 MockBuffer mockBuffer2(512);
305 SendCounterPacket sendPacket2(mockBuffer2);
306 sendPacket2.SendStreamMetaDataPacket();
307 unsigned int sizeRead = 0;
308 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
310 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
311 uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32);
313 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
314 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id
316 uint32_t totalLength = numeric_cast<uint32_t>(2 * sizeUint32 + 10 * sizeUint32 + infoSize + hardwareVersionSize +
317 softwareVersionSize + processNameSize + sizeUint32 +
318 2 * packetEntries * sizeUint32);
320 BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length
322 uint32_t offset = sizeUint32 * 2;
323 BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::PIPE_MAGIC); // pipe_magic
324 offset += sizeUint32;
325 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version
326 offset += sizeUint32;
327 BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::MAX_METADATA_PACKET_LENGTH); // max_data_len
328 offset += sizeUint32;
329 BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast<uint32_t>(getpid())); // pid
330 offset += sizeUint32;
331 uint32_t poolOffset = 10 * sizeUint32;
332 BOOST_TEST(ReadUint32(readBuffer2, offset) == (infoSize ? poolOffset : 0)); // offset_info
333 offset += sizeUint32;
334 poolOffset += infoSize;
335 BOOST_TEST(ReadUint32(readBuffer2, offset) == (hardwareVersionSize ? poolOffset : 0)); // offset_hw_version
336 offset += sizeUint32;
337 poolOffset += hardwareVersionSize;
338 BOOST_TEST(ReadUint32(readBuffer2, offset) == (softwareVersionSize ? poolOffset : 0)); // offset_sw_version
339 offset += sizeUint32;
340 poolOffset += softwareVersionSize;
341 BOOST_TEST(ReadUint32(readBuffer2, offset) == (processNameSize ? poolOffset : 0)); // offset_process_name
342 offset += sizeUint32;
343 poolOffset += processNameSize;
344 BOOST_TEST(ReadUint32(readBuffer2, offset) == (packetEntries ? poolOffset : 0)); // offset_packet_version_table
345 offset += sizeUint32;
346 BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved
348 offset += sizeUint32;
351 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetSoftwareInfo().c_str()) == 0);
355 if (hardwareVersionSize)
357 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetHardwareVersion().c_str()) == 0);
358 offset += hardwareVersionSize;
361 if (softwareVersionSize)
363 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetSoftwareVersion().c_str()) == 0);
364 offset += softwareVersionSize;
369 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetProcessName().c_str()) == 0);
370 offset += processNameSize;
375 BOOST_TEST((ReadUint32(readBuffer2, offset) >> 16) == packetEntries);
376 offset += sizeUint32;
377 for (uint32_t i = 0; i < packetEntries; ++i)
379 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 0);
380 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == i);
381 offset += sizeUint32;
382 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
383 offset += sizeUint32;
387 BOOST_TEST(offset == totalLength);
391 BOOST_AUTO_TEST_SUITE_END()