ArmNN
 22.08
ProfilingConnectionDumpToFileDecoratorTests.cpp
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 #include <client/src/ProfilingConnectionDumpToFileDecorator.hpp>
7 
8 #include <Runtime.hpp>
9 
11 
12 #include <common/include/IgnoreUnused.hpp>
13 #include <common/include/NumericCast.hpp>
14 
15 
16 #include <fstream>
17 #include <sstream>
18 
19 #include <doctest/doctest.h>
20 
21 using namespace arm::pipe;
22 
23 namespace
24 {
25 
26 const std::vector<char> g_Data = { 'd', 'u', 'm', 'm', 'y' };
27 const uint32_t g_DataLength = arm::pipe::numeric_cast<uint32_t>(g_Data.size());
28 const unsigned char* g_DataPtr = reinterpret_cast<const unsigned char*>(g_Data.data());
29 
30 class DummyProfilingConnection : public IProfilingConnection
31 {
32 public:
33  DummyProfilingConnection()
34  : m_Open(true)
35  , m_PacketData(std::make_unique<unsigned char[]>(g_DataLength))
36  {
37  // populate packet data and construct packet
38  std::memcpy(m_PacketData.get(), g_DataPtr, g_DataLength);
39  m_Packet = std::make_unique<Packet>(0u, g_DataLength, m_PacketData);
40  }
41 
42  ~DummyProfilingConnection() = default;
43 
44  bool IsOpen() const override
45  {
46  return m_Open;
47  }
48 
49  void Close() override
50  {
51  m_Open = false;
52  }
53 
54  bool WritePacket(const unsigned char* buffer, uint32_t length) override
55  {
58  return true;
59  }
60 
61  Packet ReadPacket(uint32_t timeout) override
62  {
63  arm::pipe::IgnoreUnused(timeout);
64  return std::move(*m_Packet);
65  }
66 
67 private:
68  bool m_Open;
69  std::unique_ptr<unsigned char[]> m_PacketData;
70  std::unique_ptr<Packet> m_Packet;
71 };
72 
73 std::vector<char> ReadDumpFile(const std::string& dumpFileName)
74 {
75  std::ifstream input(dumpFileName, std::ios::binary);
76  return std::vector<char>(std::istreambuf_iterator<char>(input), {});
77 }
78 
79 } // anonymous namespace
80 
81 TEST_SUITE("ProfilingConnectionDumpToFileDecoratorTests")
82 {
83 TEST_CASE("DumpIncomingInvalidFile")
84 {
85  ProfilingOptions options;
86  options.m_IncomingCaptureFile = "/";
87  options.m_OutgoingCaptureFile = "";
88  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, false);
89  CHECK_THROWS_AS(decorator.ReadPacket(0), arm::pipe::ProfilingException);
90 }
91 
92 TEST_CASE("DumpIncomingInvalidFileIgnoreErrors")
93 {
94  ProfilingOptions options;
95  options.m_IncomingCaptureFile = "/";
96  options.m_OutgoingCaptureFile = "";
97  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, true);
98  CHECK_NOTHROW(decorator.ReadPacket(0));
99 }
100 
101 TEST_CASE("DumpIncomingValidFile")
102 {
103  fs::path fileName = armnnUtils::Filesystem::NamedTempFile("Armnn-DumpIncomingValidFileTest-TempFile");
104 
105  ProfilingOptions options;
106  options.m_IncomingCaptureFile = fileName.string();
107  options.m_OutgoingCaptureFile = "";
108 
109  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, false);
110 
111  // NOTE: unique_ptr is needed here because operator=() is deleted for Packet
112  std::unique_ptr<Packet> packet;
113  CHECK_NOTHROW(packet = std::make_unique<Packet>(decorator.ReadPacket(0)));
114 
115  decorator.Close();
116 
117  std::vector<char> data = ReadDumpFile(options.m_IncomingCaptureFile);
118  const char* packetData = reinterpret_cast<const char*>(packet->GetData());
119 
120  // check if the data read back from the dump file matches the original
121  constexpr unsigned int bytesToSkip = 2u * sizeof(uint32_t); // skip header and packet length
122  int diff = std::strncmp(data.data() + bytesToSkip, packetData, g_DataLength);
123  CHECK(diff == 0);
124  fs::remove(fileName);
125 }
126 
127 TEST_CASE("DumpOutgoingInvalidFile")
128 {
129  ProfilingOptions options;
130  options.m_IncomingCaptureFile = "";
131  options.m_OutgoingCaptureFile = "/";
132  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, false);
133  CHECK_THROWS_AS(decorator.WritePacket(g_DataPtr, g_DataLength), arm::pipe::ProfilingException);
134 }
135 
136 TEST_CASE("DumpOutgoingInvalidFileIgnoreErrors")
137 {
138  ProfilingOptions options;
139  options.m_IncomingCaptureFile = "";
140  options.m_OutgoingCaptureFile = "/";
141 
142  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, true);
143  CHECK_NOTHROW(decorator.WritePacket(g_DataPtr, g_DataLength));
144 
145  bool success = decorator.WritePacket(g_DataPtr, g_DataLength);
146  CHECK(!success);
147 }
148 
149 TEST_CASE("DumpOutgoingValidFile")
150 {
151  fs::path fileName = armnnUtils::Filesystem::NamedTempFile("Armnn-DumpOutgoingValidFileTest-TempFile");
152 
153  ProfilingOptions options;
154  options.m_IncomingCaptureFile = "";
155  options.m_OutgoingCaptureFile = fileName.string();
156 
157  ProfilingConnectionDumpToFileDecorator decorator(std::make_unique<DummyProfilingConnection>(), options, false);
158 
159  bool success = false;
160  CHECK_NOTHROW(success = decorator.WritePacket(g_DataPtr, g_DataLength));
161  CHECK(success);
162 
163  decorator.Close();
164 
165  std::vector<char> data = ReadDumpFile(options.m_OutgoingCaptureFile);
166 
167  // check if the data read back from the dump file matches the original
168  int diff = std::strncmp(data.data(), g_Data.data(), g_DataLength);
169  CHECK(diff == 0);
170  fs::remove(fileName);
171 }
172 
173 }
TEST_SUITE("ProfilingConnectionDumpToFileDecoratorTests")
void IgnoreUnused(Ts &&...)
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
fs::path NamedTempFile(const char *fileName)
Returns a path to a file in the system temporary folder. If the file existed it will be deleted...
Definition: Filesystem.cpp:24