IVGCVSW-3691 Basic refactoring in view of upcoming work in the profiler
[platform/upstream/armnn.git] / src / profiling / test / SendCounterPacketTests.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "../SendCounterPacket.hpp"
7 #include "../ProfilingUtils.hpp"
8 #include "../EncodeVersion.hpp"
9
10 #include <armnn/Exceptions.hpp>
11
12 #include <boost/test/unit_test.hpp>
13 #include <boost/numeric/conversion/cast.hpp>
14
15 #include <chrono>
16 #include <iostream>
17
18 BOOST_AUTO_TEST_SUITE(SendCounterPacketTests)
19
20 using namespace armnn::profiling;
21
22 class MockBuffer : public IBufferWrapper
23 {
24 public:
25     MockBuffer(unsigned int size)
26     : m_BufferSize(size),
27       m_Buffer(std::make_unique<unsigned char[]>(size)) {}
28
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
40         return m_Buffer.get();
41     }
42
43     void Commit(unsigned int size) override {}
44
45     const unsigned char* GetReadBuffer(unsigned int& size) override
46     {
47         size = static_cast<unsigned int>(strlen(reinterpret_cast<const char*>(m_Buffer.get())) + 1);
48         return m_Buffer.get();
49     }
50
51     void Release( unsigned int size) override {}
52
53 private:
54     unsigned int m_BufferSize;
55     std::unique_ptr<unsigned char[]> m_Buffer;
56 };
57
58 class MockSendCounterPacket : public ISendCounterPacket
59 {
60 public:
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
71     void SendCounterDirectoryPacket(const CounterDirectory& counterDirectory) override
72     {
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
79     void SendPeriodicCounterCapturePacket(uint64_t timestamp,
80                                           const std::vector<std::pair<uint16_t, uint32_t>>& values) override
81     {
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
101 private:
102     IBufferWrapper& m_Buffer;
103 };
104
105 BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest)
106 {
107     unsigned int size = 0;
108
109     MockBuffer mockBuffer(512);
110     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
117     CounterDirectory counterDirectory(1, "counter_directory", 0, 0, 0);
118     sendCounterPacket.SendCounterDirectoryPacket(counterDirectory);
119
120     BOOST_TEST(strcmp(buffer, "SendCounterDirectoryPacket") == 0);
121
122     uint64_t timestamp = 0;
123     std::vector<std::pair<uint16_t, uint32_t>> indexValuePairs;
124
125     sendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, indexValuePairs);
126
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
137 BOOST_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),
146                       armnn::profiling::BufferExhaustion);
147
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
200 BOOST_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
277 BOOST_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);
286     BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion);
287
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
390 BOOST_AUTO_TEST_SUITE_END()