blob: 626a5a65896873ab3a2d6551fb80f65f68405bad [file] [log] [blame]
Ferran Balagueraf5c46b2019-08-30 15:49:15 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Ferran Balaguer73882172019-09-02 16:39:42 +01006#include "../SendCounterPacket.hpp"
7#include "../ProfilingUtils.hpp"
Ferran Balaguer47d0fe92019-09-04 16:47:34 +01008#include "../EncodeVersion.hpp"
Ferran Balagueraf5c46b2019-08-30 15:49:15 +01009
Ferran Balaguer73882172019-09-02 16:39:42 +010010#include <armnn/Exceptions.hpp>
11
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010012#include <boost/test/unit_test.hpp>
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010013#include <boost/numeric/conversion/cast.hpp>
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010014
Francis Murtagh3a161982019-09-04 15:25:02 +010015#include <chrono>
Ferran Balaguer73882172019-09-02 16:39:42 +010016#include <iostream>
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010017
18BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
19
20using namespace armnn::profiling;
21
22class MockBuffer : public IBufferWrapper
23{
24public:
Ferran Balaguer73882172019-09-02 16:39:42 +010025 MockBuffer(unsigned int size)
26 : m_BufferSize(size),
27 m_Buffer(std::make_unique<unsigned char[]>(size)) {}
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010028
29 unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
30 {
31 if (requestedSize > m_BufferSize)
32 {
33 reservedSize = m_BufferSize;
34 }
35 else
36 {
37 reservedSize = requestedSize;
38 }
39
Ferran Balaguer73882172019-09-02 16:39:42 +010040 return m_Buffer.get();
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010041 }
42
43 void Commit(unsigned int size) override {}
44
45 const unsigned char* GetReadBuffer(unsigned int& size) override
46 {
Ferran Balaguer73882172019-09-02 16:39:42 +010047 size = static_cast<unsigned int>(strlen(reinterpret_cast<const char*>(m_Buffer.get())) + 1);
48 return m_Buffer.get();
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010049 }
50
51 void Release( unsigned int size) override {}
52
53private:
Ferran Balaguer73882172019-09-02 16:39:42 +010054 unsigned int m_BufferSize;
55 std::unique_ptr<unsigned char[]> m_Buffer;
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010056};
57
58class MockSendCounterPacket : public ISendCounterPacket
59{
60public:
61 MockSendCounterPacket(IBufferWrapper& sendBuffer) : m_Buffer(sendBuffer) {}
62
63 void SendStreamMetaDataPacket() override
64 {
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);
69 }
70
Matteo Martincigh149528e2019-09-05 12:02:04 +010071 void SendCounterDirectoryPacket(const CounterDirectory& counterDirectory) override
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010072 {
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);
77 }
78
Francis Murtagh3a161982019-09-04 15:25:02 +010079 void SendPeriodicCounterCapturePacket(uint64_t timestamp,
80 const std::vector<std::pair<uint16_t, uint32_t>>& values) override
Ferran Balagueraf5c46b2019-08-30 15:49:15 +010081 {
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);
86 }
87
88 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
89 const std::vector<uint16_t>& selectedCounterIds) override
90 {
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);
96 }
97
98 void SetReadyToRead() override
99 {}
100
101private:
102 IBufferWrapper& m_Buffer;
103};
104
105BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
106{
107 unsigned int size = 0;
108
Ferran Balaguer73882172019-09-02 16:39:42 +0100109 MockBuffer mockBuffer(512);
Ferran Balagueraf5c46b2019-08-30 15:49:15 +0100110 MockSendCounterPacket sendCounterPacket(mockBuffer);
111
112 sendCounterPacket.SendStreamMetaDataPacket();
113 const char* buffer = reinterpret_cast<const char*>(mockBuffer.GetReadBuffer(size));
114
115 BOOST_TEST(strcmp(buffer, "SendStreamMetaDataPacket") == 0);
116
Matteo Martincigh149528e2019-09-05 12:02:04 +0100117 CounterDirectory counterDirectory(1, "counter_directory", 0, 0, 0);
118 sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
Ferran Balagueraf5c46b2019-08-30 15:49:15 +0100119
120 BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
121
122 uint64_t timestamp = 0;
Francis Murtagh3a161982019-09-04 15:25:02 +0100123 std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
124
125 sendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
Ferran Balagueraf5c46b2019-08-30 15:49:15 +0100126
127 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterCapturePacket") == 0);
128
129 uint32_t capturePeriod = 0;
130 std::vector<uint16_t> selectedCounterIds;
131 sendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
132
133 BOOST_TEST(strcmp(buffer, "SendPeriodicCounterSelectionPacket") == 0);
134
135}
136
Ferran Balaguer73882172019-09-02 16:39:42 +0100137BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest)
138{
139 // Error no space left in buffer
140 MockBuffer mockBuffer1(10);
141 SendCounterPacket sendPacket1(mockBuffer1);
142
143 uint32_t capturePeriod = 1000;
144 std::vector<uint16_t> selectedCounterIds;
145 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds),
Matteo Martincigh149528e2019-09-05 12:02:04 +0100146 armnn::profiling::BufferExhaustion);
Ferran Balaguer73882172019-09-02 16:39:42 +0100147
148 // Packet without any counters
149 MockBuffer mockBuffer2(512);
150 SendCounterPacket sendPacket2(mockBuffer2);
151
152 sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
153 unsigned int sizeRead = 0;
154 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
155
156 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
157 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
158 uint32_t period = ReadUint32(readBuffer2, 8);
159
160 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
161 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
162 BOOST_TEST(headerWord1 == 4); // data lenght
163 BOOST_TEST(period == 1000); // capture period
164
165 // Full packet message
166 MockBuffer mockBuffer3(512);
167 SendCounterPacket sendPacket3(mockBuffer3);
168
169 selectedCounterIds.reserve(5);
170 selectedCounterIds.emplace_back(100);
171 selectedCounterIds.emplace_back(200);
172 selectedCounterIds.emplace_back(300);
173 selectedCounterIds.emplace_back(400);
174 selectedCounterIds.emplace_back(500);
175 sendPacket3.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds);
176 sizeRead = 0;
177 const unsigned char* readBuffer3 = mockBuffer3.GetReadBuffer(sizeRead);
178
179 headerWord0 = ReadUint32(readBuffer3, 0);
180 headerWord1 = ReadUint32(readBuffer3, 4);
181 period = ReadUint32(readBuffer3, 8);
182
183 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
184 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 4); // packet id
185 BOOST_TEST(headerWord1 == 14); // data lenght
186 BOOST_TEST(period == 1000); // capture period
187
188 uint16_t counterId = 0;
189 uint32_t offset = 12;
190
191 // Counter Ids
192 for(const uint16_t& id : selectedCounterIds)
193 {
194 counterId = ReadUint16(readBuffer3, offset);
195 BOOST_TEST(counterId == id);
196 offset += 2;
197 }
198}
199
Francis Murtagh3a161982019-09-04 15:25:02 +0100200BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest)
201{
202 // Error no space left in buffer
203 MockBuffer mockBuffer1(10);
204 SendCounterPacket sendPacket1(mockBuffer1);
205
206 auto captureTimestamp = std::chrono::steady_clock::now();
207 uint64_t time = static_cast<uint64_t >(captureTimestamp.time_since_epoch().count());
208 std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
209
210 BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterCapturePacket(time, indexValuePairs),
211 BufferExhaustion);
212
213 // Packet without any counters
214 MockBuffer mockBuffer2(512);
215 SendCounterPacket sendPacket2(mockBuffer2);
216
217 sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs);
218 unsigned int sizeRead = 0;
219 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
220
221 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
222 uint32_t headerWord1 = ReadUint32(readBuffer2, 4);
223 uint64_t readTimestamp = ReadUint64(readBuffer2, 8);
224
225 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 1); // packet family
226 BOOST_TEST(((headerWord0 >> 19) & 0x3F) == 0); // packet class
227 BOOST_TEST(((headerWord0 >> 16) & 0x3) == 0); // packet type
228 BOOST_TEST(headerWord1 == 8); // data length
229 BOOST_TEST(time == readTimestamp); // capture period
230
231 // Full packet message
232 MockBuffer mockBuffer3(512);
233 SendCounterPacket sendPacket3(mockBuffer3);
234
235 indexValuePairs.reserve(5);
236 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(0, 100));
237 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(1, 200));
238 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(2, 300));
239 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(3, 400));
240 indexValuePairs.emplace_back(std::make_pair<uint16_t, uint32_t >(4, 500));
241 sendPacket3.SendPeriodicCounterCapturePacket(time, indexValuePairs);
242 sizeRead = 0;
243 const unsigned char* readBuffer3 = mockBuffer3.GetReadBuffer(sizeRead);
244
245 headerWord0 = ReadUint32(readBuffer3, 0);
246 headerWord1 = ReadUint32(readBuffer3, 4);
247 uint64_t readTimestamp2 = ReadUint64(readBuffer3, 8);
248
249 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 1); // packet family
250 BOOST_TEST(((headerWord0 >> 19) & 0x3F) == 0); // packet class
251 BOOST_TEST(((headerWord0 >> 16) & 0x3) == 0); // packet type
252 BOOST_TEST(headerWord1 == 38); // data length
253 BOOST_TEST(time == readTimestamp2); // capture period
254
255 uint16_t counterIndex = 0;
256 uint32_t counterValue = 100;
257 uint32_t offset = 16;
258
259 // Counter Ids
260 for (auto it = indexValuePairs.begin(), end = indexValuePairs.end(); it != end; ++it)
261 {
262 // Check Counter Index
263 uint16_t readIndex = ReadUint16(readBuffer3, offset);
264 BOOST_TEST(counterIndex == readIndex);
265 counterIndex++;
266 offset += 2;
267
268 // Check Counter Value
269 uint32_t readValue = ReadUint32(readBuffer3, offset);
270 BOOST_TEST(counterValue == readValue);
271 counterValue += 100;
272 offset += 4;
273 }
274
275}
276
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100277BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest)
278{
279 using boost::numeric_cast;
280
281 uint32_t sizeUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
282
283 // Error no space left in buffer
284 MockBuffer mockBuffer1(10);
285 SendCounterPacket sendPacket1(mockBuffer1);
Matteo Martincigh149528e2019-09-05 12:02:04 +0100286 BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion);
Ferran Balaguer47d0fe92019-09-04 16:47:34 +0100287
288 // Full metadata packet
289
290 std::string processName = GetProcessName().substr(0, 60);
291
292 uint32_t infoSize = numeric_cast<uint32_t>(GetSoftwareInfo().size()) > 0 ?
293 numeric_cast<uint32_t>(GetSoftwareInfo().size()) + 1 : 0;
294 uint32_t hardwareVersionSize = numeric_cast<uint32_t>(GetHardwareVersion().size()) > 0 ?
295 numeric_cast<uint32_t>(GetHardwareVersion().size()) + 1 : 0;
296 uint32_t softwareVersionSize = numeric_cast<uint32_t>(GetSoftwareVersion().size()) > 0 ?
297 numeric_cast<uint32_t>(GetSoftwareVersion().size()) + 1 : 0;
298 uint32_t processNameSize = numeric_cast<uint32_t>(processName.size()) > 0 ?
299 numeric_cast<uint32_t>(processName.size()) + 1 : 0;
300
301 uint32_t packetEntries = 5;
302
303 MockBuffer mockBuffer2(512);
304 SendCounterPacket sendPacket2(mockBuffer2);
305 sendPacket2.SendStreamMetaDataPacket();
306 unsigned int sizeRead = 0;
307 const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead);
308
309 uint32_t headerWord0 = ReadUint32(readBuffer2, 0);
310 uint32_t headerWord1 = ReadUint32(readBuffer2, sizeUint32);
311
312 BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 0); // packet family
313 BOOST_TEST(((headerWord0 >> 16) & 0x3FF) == 0); // packet id
314
315 uint32_t totalLength = numeric_cast<uint32_t>(2 * sizeUint32 + 10 * sizeUint32 + infoSize + hardwareVersionSize +
316 softwareVersionSize + processNameSize + sizeUint32 +
317 2 * packetEntries * sizeUint32);
318
319 BOOST_TEST(headerWord1 == totalLength - (2 * sizeUint32)); // data length
320
321 uint32_t offset = sizeUint32 * 2;
322 BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::PIPE_MAGIC); // pipe_magic
323 offset += sizeUint32;
324 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0)); // stream_metadata_version
325 offset += sizeUint32;
326 BOOST_TEST(ReadUint32(readBuffer2, offset) == SendCounterPacket::MAX_METADATA_PACKET_LENGTH); // max_data_len
327 offset += sizeUint32;
328 BOOST_TEST(ReadUint32(readBuffer2, offset) == numeric_cast<uint32_t>(getpid())); // pid
329 offset += sizeUint32;
330 uint32_t poolOffset = 10 * sizeUint32;
331 BOOST_TEST(ReadUint32(readBuffer2, offset) == (infoSize ? poolOffset : 0)); // offset_info
332 offset += sizeUint32;
333 poolOffset += infoSize;
334 BOOST_TEST(ReadUint32(readBuffer2, offset) == (hardwareVersionSize ? poolOffset : 0)); // offset_hw_version
335 offset += sizeUint32;
336 poolOffset += hardwareVersionSize;
337 BOOST_TEST(ReadUint32(readBuffer2, offset) == (softwareVersionSize ? poolOffset : 0)); // offset_sw_version
338 offset += sizeUint32;
339 poolOffset += softwareVersionSize;
340 BOOST_TEST(ReadUint32(readBuffer2, offset) == (processNameSize ? poolOffset : 0)); // offset_process_name
341 offset += sizeUint32;
342 poolOffset += processNameSize;
343 BOOST_TEST(ReadUint32(readBuffer2, offset) == (packetEntries ? poolOffset : 0)); // offset_packet_version_table
344 offset += sizeUint32;
345 BOOST_TEST(ReadUint32(readBuffer2, offset) == 0); // reserved
346
347 offset += sizeUint32;
348 if (infoSize)
349 {
350 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetSoftwareInfo().c_str()) == 0);
351 offset += infoSize;
352 }
353
354 if (hardwareVersionSize)
355 {
356 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetHardwareVersion().c_str()) == 0);
357 offset += hardwareVersionSize;
358 }
359
360 if (softwareVersionSize)
361 {
362 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetSoftwareVersion().c_str()) == 0);
363 offset += softwareVersionSize;
364 }
365
366 if (processNameSize)
367 {
368 BOOST_TEST(strcmp(reinterpret_cast<const char *>(&readBuffer2[offset]), GetProcessName().c_str()) == 0);
369 offset += processNameSize;
370 }
371
372 if (packetEntries)
373 {
374 BOOST_TEST((ReadUint32(readBuffer2, offset) >> 16) == packetEntries);
375 offset += sizeUint32;
376 for (uint32_t i = 0; i < packetEntries; ++i)
377 {
378 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 26) & 0x3F) == 0);
379 BOOST_TEST(((ReadUint32(readBuffer2, offset) >> 16) & 0x3FF) == i);
380 offset += sizeUint32;
381 BOOST_TEST(ReadUint32(readBuffer2, offset) == EncodeVersion(1, 0, 0));
382 offset += sizeUint32;
383 }
384 }
385
386 BOOST_TEST(offset == totalLength);
387}
388
389
Ferran Balagueraf5c46b2019-08-30 15:49:15 +0100390BOOST_AUTO_TEST_SUITE_END()