ArmNN
 20.08
ProfilingTests.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "ProfilingMocks.hpp"
9 
10 #include <armnn/Logging.hpp>
12 
13 #include <IProfilingConnection.hpp>
14 #include <ProfilingService.hpp>
15 
16 #include <common/include/CommandHandlerFunctor.hpp>
17 
18 
19 #include <boost/test/unit_test.hpp>
20 
21 #include <chrono>
22 #include <thread>
23 
24 namespace armnn
25 {
26 
27 namespace profiling
28 {
29 
31 {
32 public:
34  {
35  // Set the new log level
36  armnn::ConfigureLogging(true, true, severity);
37  }
39  {
40  // The default log level for unit tests is "Fatal"
42  }
43 };
44 
46 {
47 public:
48  StreamRedirector(std::ostream& stream, std::streambuf* newStreamBuffer)
49  : m_Stream(stream)
50  , m_BackupBuffer(m_Stream.rdbuf(newStreamBuffer))
51  {}
52 
53  ~StreamRedirector() { CancelRedirect(); }
54 
56  {
57  // Only cancel the redirect once.
58  if (m_BackupBuffer != nullptr )
59  {
60  m_Stream.rdbuf(m_BackupBuffer);
61  m_BackupBuffer = nullptr;
62  }
63  }
64 
65 private:
66  std::ostream& m_Stream;
67  std::streambuf* m_BackupBuffer;
68 };
69 
71 {
72 public:
73  TestProfilingConnectionBase() = default;
74  ~TestProfilingConnectionBase() = default;
75 
76  bool IsOpen() const override { return true; }
77 
78  void Close() override {}
79 
80  bool WritePacket(const unsigned char* buffer, uint32_t length) override
81  {
82  IgnoreUnused(buffer, length);
83 
84  return false;
85  }
86 
87  arm::pipe::Packet ReadPacket(uint32_t timeout) override
88  {
89  // First time we're called return a connection ack packet. After that always timeout.
90  if (m_FirstCall)
91  {
92  m_FirstCall = false;
93  // Return connection acknowledged packet
94  return arm::pipe::Packet(65536);
95  }
96  else
97  {
98  std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
99  throw armnn::TimeoutException("Simulate a timeout error\n");
100  }
101  }
102 
103  bool m_FirstCall = true;
104 };
105 
107 {
108 public:
110  : m_ReadRequests(0)
111  {}
112 
113  arm::pipe::Packet ReadPacket(uint32_t timeout) override
114  {
115  // Return connection acknowledged packet after three timeouts
116  if (m_ReadRequests % 3 == 0)
117  {
118  std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
119  ++m_ReadRequests;
120  throw armnn::TimeoutException("Simulate a timeout error\n");
121  }
122 
123  return arm::pipe::Packet(65536);
124  }
125 
127  {
128  return m_ReadRequests.load();
129  }
130 
131 private:
132  std::atomic<int> m_ReadRequests;
133 };
134 
136 {
137 public:
139  : m_ReadRequests(0)
140  {}
141 
142  arm::pipe::Packet ReadPacket(uint32_t timeout) override
143  {
144  IgnoreUnused(timeout);
145  ++m_ReadRequests;
146  throw armnn::Exception("Simulate a non-timeout error");
147  }
148 
150  {
151  return m_ReadRequests.load();
152  }
153 
154 private:
155  std::atomic<int> m_ReadRequests;
156 };
157 
159 {
160 public:
161  arm::pipe::Packet ReadPacket(uint32_t timeout) override
162  {
163  IgnoreUnused(timeout);
164  // Connection Acknowledged Packet header (word 0, word 1 is always zero):
165  // 26:31 [6] packet_family: Control Packet Family, value 0b000000
166  // 16:25 [10] packet_id: Packet identifier, value 0b0000000001
167  // 8:15 [8] reserved: Reserved, value 0b00000000
168  // 0:7 [8] reserved: Reserved, value 0b00000000
169  uint32_t packetFamily = 0;
170  uint32_t packetId = 37; // Wrong packet id!!!
171  uint32_t header = ((packetFamily & 0x0000003F) << 26) | ((packetId & 0x000003FF) << 16);
172 
173  return arm::pipe::Packet(header);
174  }
175 };
176 
177 class TestFunctorA : public arm::pipe::CommandHandlerFunctor
178 {
179 public:
180  using CommandHandlerFunctor::CommandHandlerFunctor;
181 
182  int GetCount() { return m_Count; }
183 
184  void operator()(const arm::pipe::Packet& packet) override
185  {
186  IgnoreUnused(packet);
187  m_Count++;
188  }
189 
190 private:
191  int m_Count = 0;
192 };
193 
195 {
196  using TestFunctorA::TestFunctorA;
197 };
198 
200 {
201  using TestFunctorA::TestFunctorA;
202 };
203 
205 {
206 public:
207  using MockProfilingConnectionFactoryPtr = std::unique_ptr<MockProfilingConnectionFactory>;
208 
210  : ProfilingService()
211  , m_ProfilingService(profilingService)
212  , m_MockProfilingConnectionFactory(new MockProfilingConnectionFactory())
213  , m_BackupProfilingConnectionFactory(nullptr)
214 
215  {
216  BOOST_CHECK(m_MockProfilingConnectionFactory);
217  SwapProfilingConnectionFactory(m_ProfilingService,
218  m_MockProfilingConnectionFactory.get(),
219  m_BackupProfilingConnectionFactory);
220  BOOST_CHECK(m_BackupProfilingConnectionFactory);
221  }
223  {
224  BOOST_CHECK(m_BackupProfilingConnectionFactory);
225  IProfilingConnectionFactory* temp = nullptr;
226  SwapProfilingConnectionFactory(m_ProfilingService,
227  m_BackupProfilingConnectionFactory,
228  temp);
229  }
230 
232  {
233  IProfilingConnection* profilingConnection = GetProfilingConnection(m_ProfilingService);
234  return PolymorphicDowncast<MockProfilingConnection*>(profilingConnection);
235  }
236 
238  {
239  TransitionToState(m_ProfilingService, newState);
240  }
241 
242  long WaitForPacketsSent(MockProfilingConnection* mockProfilingConnection,
244  uint32_t length = 0,
245  uint32_t timeout = 1000)
246  {
247  long packetCount = mockProfilingConnection->CheckForPacket({ packetType, length });
248  // The first packet we receive may not be the one we are looking for, so keep looping until till we find it,
249  // or until WaitForPacketsSent times out
250  while(packetCount == 0 && timeout != 0)
251  {
252  std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
253  // Wait for a notification from the send thread
254  ProfilingService::WaitForPacketSent(m_ProfilingService, timeout);
255 
256  std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
257 
258  // We need to make sure the timeout does not reset each time we call WaitForPacketsSent
259  uint32_t elapsedTime = static_cast<uint32_t>(
260  std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
261 
262  packetCount = mockProfilingConnection->CheckForPacket({packetType, length});
263 
264  if (elapsedTime > timeout)
265  {
266  break;
267  }
268 
269  timeout -= elapsedTime;
270  }
271  return packetCount;
272  }
273 
274 private:
275  armnn::profiling::ProfilingService& m_ProfilingService;
276  MockProfilingConnectionFactoryPtr m_MockProfilingConnectionFactory;
277  IProfilingConnectionFactory* m_BackupProfilingConnectionFactory;
278 };
279 
280 } // namespace profiling
281 
282 } // namespace armnn
LogLevelSwapper(armnn::LogSeverity severity)
SwapProfilingConnectionFactoryHelper(armnn::profiling::ProfilingService &profilingService)
long WaitForPacketsSent(MockProfilingConnection *mockProfilingConnection, MockProfilingConnection::PacketType packetType, uint32_t length=0, uint32_t timeout=1000)
StreamRedirector(std::ostream &stream, std::streambuf *newStreamBuffer)
void ConfigureLogging(bool printToStandardOutput, bool printToDebugOutput, LogSeverity severity)
Configures the logging behaviour of the ARMNN library.
Definition: Utils.cpp:10
arm::pipe::Packet ReadPacket(uint32_t timeout) override
Copyright (c) 2020 ARM Limited.
void IgnoreUnused(Ts &&...)
bool WaitForPacketSent(ProfilingService &instance, uint32_t timeout=1000)
arm::pipe::Packet ReadPacket(uint32_t timeout) override
bool WritePacket(const unsigned char *buffer, uint32_t length) override
void operator()(const arm::pipe::Packet &packet) override
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
long CheckForPacket(const std::pair< PacketType, uint32_t > packetInfo)
arm::pipe::Packet ReadPacket(uint32_t timeout) override
arm::pipe::Packet ReadPacket(uint32_t timeout) override
LogSeverity
Definition: Utils.hpp:12
std::unique_ptr< MockProfilingConnectionFactory > MockProfilingConnectionFactoryPtr