• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #include <armnnUtils/Filesystem.hpp>
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:
DummyProfilingConnection()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 
IsOpen() const44     bool IsOpen() const override
45     {
46         return m_Open;
47     }
48 
Close()49     void Close() override
50     {
51         m_Open = false;
52     }
53 
WritePacket(const unsigned char * buffer,uint32_t length)54     bool WritePacket(const unsigned char* buffer, uint32_t length) override
55     {
56         arm::pipe::IgnoreUnused(buffer);
57         arm::pipe::IgnoreUnused(length);
58         return true;
59     }
60 
ReadPacket(uint32_t timeout)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 
ReadDumpFile(const std::string & dumpFileName)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 }
174