blob: 65c182b6221af3cd7eb14a51d8a4abc0b20b1659 [file] [log] [blame]
Matteo Martincighd0613b52019-10-09 16:47:04 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include "SendCounterPacketTests.hpp"
9
10#include <CommandHandlerFunctor.hpp>
11#include <IProfilingConnection.hpp>
Matteo Martincighd0613b52019-10-09 16:47:04 +010012#include <Logging.hpp>
13#include <ProfilingService.hpp>
14
Narumol Prangnawarat85ad78c2019-11-18 15:34:23 +000015#include <boost/polymorphic_cast.hpp>
Matteo Martincighd0613b52019-10-09 16:47:04 +010016#include <boost/test/unit_test.hpp>
17
18#include <chrono>
Matteo Martincighd0613b52019-10-09 16:47:04 +010019#include <thread>
20
21namespace armnn
22{
23
24namespace profiling
25{
26
27struct LogLevelSwapper
28{
29public:
30 LogLevelSwapper(armnn::LogSeverity severity)
31 {
32 // Set the new log level
33 armnn::ConfigureLogging(true, true, severity);
34 }
35 ~LogLevelSwapper()
36 {
37 // The default log level for unit tests is "Fatal"
38 armnn::ConfigureLogging(true, true, armnn::LogSeverity::Fatal);
39 }
40};
41
Matteo Martincighd0613b52019-10-09 16:47:04 +010042struct StreamRedirector
43{
44public:
45 StreamRedirector(std::ostream& stream, std::streambuf* newStreamBuffer)
46 : m_Stream(stream)
47 , m_BackupBuffer(m_Stream.rdbuf(newStreamBuffer))
48 {}
Colm Donelan2ba48d22019-11-29 09:10:59 +000049
50 ~StreamRedirector() { CancelRedirect(); }
51
52 void CancelRedirect()
53 {
54 // Only cancel the redirect once.
55 if (m_BackupBuffer != nullptr )
56 {
57 m_Stream.rdbuf(m_BackupBuffer);
58 m_BackupBuffer = nullptr;
59 }
60 }
Matteo Martincighd0613b52019-10-09 16:47:04 +010061
62private:
63 std::ostream& m_Stream;
64 std::streambuf* m_BackupBuffer;
65};
66
67class TestProfilingConnectionBase : public IProfilingConnection
68{
69public:
70 TestProfilingConnectionBase() = default;
71 ~TestProfilingConnectionBase() = default;
72
73 bool IsOpen() const override { return true; }
74
75 void Close() override {}
76
77 bool WritePacket(const unsigned char* buffer, uint32_t length) override { return false; }
78
79 Packet ReadPacket(uint32_t timeout) override
80 {
Colm Donelan2ba48d22019-11-29 09:10:59 +000081 // First time we're called return a connection ack packet. After that always timeout.
82 if (m_FirstCall)
83 {
84 m_FirstCall = false;
85 // Return connection acknowledged packet
86 return Packet(65536);
87 }
88 else
89 {
90 std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
91 throw armnn::TimeoutException("Simulate a timeout error\n");
92 }
Matteo Martincighd0613b52019-10-09 16:47:04 +010093 }
Colm Donelan2ba48d22019-11-29 09:10:59 +000094
95 bool m_FirstCall = true;
Matteo Martincighd0613b52019-10-09 16:47:04 +010096};
97
98class TestProfilingConnectionTimeoutError : public TestProfilingConnectionBase
99{
100public:
101 TestProfilingConnectionTimeoutError()
102 : m_ReadRequests(0)
103 {}
104
105 Packet ReadPacket(uint32_t timeout) override
106 {
Colm Donelan2ba48d22019-11-29 09:10:59 +0000107 // Return connection acknowledged packet after three timeouts
108 if (m_ReadRequests % 3 == 0)
Matteo Martincighd0613b52019-10-09 16:47:04 +0100109 {
Colm Donelan2ba48d22019-11-29 09:10:59 +0000110 std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
111 ++m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100112 throw armnn::TimeoutException("Simulate a timeout error\n");
113 }
114
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100115 return Packet(65536);
Matteo Martincighd0613b52019-10-09 16:47:04 +0100116 }
117
Colm Donelan2ba48d22019-11-29 09:10:59 +0000118 int ReadCalledCount()
119 {
120 return m_ReadRequests.load();
121 }
122
Matteo Martincighd0613b52019-10-09 16:47:04 +0100123private:
Colm Donelan2ba48d22019-11-29 09:10:59 +0000124 std::atomic<int> m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100125};
126
127class TestProfilingConnectionArmnnError : public TestProfilingConnectionBase
128{
129public:
Colm Donelan2ba48d22019-11-29 09:10:59 +0000130 TestProfilingConnectionArmnnError()
131 : m_ReadRequests(0)
132 {}
133
Matteo Martincighd0613b52019-10-09 16:47:04 +0100134 Packet ReadPacket(uint32_t timeout) override
135 {
Colm Donelan2ba48d22019-11-29 09:10:59 +0000136 ++m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100137 throw armnn::Exception("Simulate a non-timeout error");
138 }
Colm Donelan2ba48d22019-11-29 09:10:59 +0000139
140 int ReadCalledCount()
141 {
142 return m_ReadRequests.load();
143 }
144
145private:
146 std::atomic<int> m_ReadRequests;
Matteo Martincighd0613b52019-10-09 16:47:04 +0100147};
148
149class TestFunctorA : public CommandHandlerFunctor
150{
151public:
152 using CommandHandlerFunctor::CommandHandlerFunctor;
153
154 int GetCount() { return m_Count; }
155
156 void operator()(const Packet& packet) override
157 {
158 m_Count++;
159 }
160
161private:
162 int m_Count = 0;
163};
164
165class TestFunctorB : public TestFunctorA
166{
167 using TestFunctorA::TestFunctorA;
168};
169
170class TestFunctorC : public TestFunctorA
171{
172 using TestFunctorA::TestFunctorA;
173};
174
Matteo Martincighd0613b52019-10-09 16:47:04 +0100175class SwapProfilingConnectionFactoryHelper : public ProfilingService
176{
177public:
178 using MockProfilingConnectionFactoryPtr = std::unique_ptr<MockProfilingConnectionFactory>;
179
180 SwapProfilingConnectionFactoryHelper()
181 : ProfilingService()
182 , m_MockProfilingConnectionFactory(new MockProfilingConnectionFactory())
183 , m_BackupProfilingConnectionFactory(nullptr)
184 {
185 BOOST_CHECK(m_MockProfilingConnectionFactory);
186 SwapProfilingConnectionFactory(ProfilingService::Instance(),
187 m_MockProfilingConnectionFactory.get(),
188 m_BackupProfilingConnectionFactory);
189 BOOST_CHECK(m_BackupProfilingConnectionFactory);
190 }
191 ~SwapProfilingConnectionFactoryHelper()
192 {
193 BOOST_CHECK(m_BackupProfilingConnectionFactory);
194 IProfilingConnectionFactory* temp = nullptr;
195 SwapProfilingConnectionFactory(ProfilingService::Instance(),
196 m_BackupProfilingConnectionFactory,
197 temp);
198 }
199
200 MockProfilingConnection* GetMockProfilingConnection()
201 {
202 IProfilingConnection* profilingConnection = GetProfilingConnection(ProfilingService::Instance());
203 return boost::polymorphic_downcast<MockProfilingConnection*>(profilingConnection);
204 }
205
Matteo Martincigh8efc5002019-10-10 14:30:29 +0100206 void ForceTransitionToState(ProfilingState newState)
207 {
208 TransitionToState(ProfilingService::Instance(), newState);
209 }
210
Colm Donelan2ba48d22019-11-29 09:10:59 +0000211 void WaitForProfilingPacketsSent(MockProfilingConnection* mockProfilingConnection, uint32_t timeout = 1000)
Matteo Martincighe8485382019-10-10 14:08:21 +0100212 {
Colm Donelan2ba48d22019-11-29 09:10:59 +0000213 if (!mockProfilingConnection->HasWrittenData())
214 {
215 WaitForPacketSent(ProfilingService::Instance(), timeout);
216 // It's possible the wait has timed out. Check there is some data.
217 if (!mockProfilingConnection->HasWrittenData())
218 {
219 throw RuntimeException("ProfilingTests::WaitForProfilingPacketsSent timeout waiting for packet.");
220 }
221 }
Matteo Martincighe8485382019-10-10 14:08:21 +0100222 }
223
Matteo Martincighd0613b52019-10-09 16:47:04 +0100224private:
225 MockProfilingConnectionFactoryPtr m_MockProfilingConnectionFactory;
226 IProfilingConnectionFactory* m_BackupProfilingConnectionFactory;
227};
228
229} // namespace profiling
230
231} // namespace armnn