1099543e4SBrad Bishop // SPDX-License-Identifier: Apache-2.0
2099543e4SBrad Bishop 
3099543e4SBrad Bishop #include "../functions.hpp"
4099543e4SBrad Bishop 
5099543e4SBrad Bishop #include <stdlib.h>
6099543e4SBrad Bishop 
7099543e4SBrad Bishop #include <array>
8099543e4SBrad Bishop #include <cerrno>
9099543e4SBrad Bishop #include <filesystem>
10099543e4SBrad Bishop #include <fstream>
11099543e4SBrad Bishop #include <map>
12099543e4SBrad Bishop #include <string>
13099543e4SBrad Bishop #include <vector>
14099543e4SBrad Bishop 
15099543e4SBrad Bishop #include <gtest/gtest.h>
16099543e4SBrad Bishop 
17099543e4SBrad Bishop using namespace std::string_literals;
18099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testSingleMatch)19099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testSingleMatch)
20099543e4SBrad Bishop {
21099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
22099543e4SBrad Bishop         {"system-foo"s, {".EXT"s}},
23099543e4SBrad Bishop     }};
24099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s}, extensions;
25099543e4SBrad Bishop     auto found =
26099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
27099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
28099543e4SBrad Bishop     EXPECT_TRUE(found);
29099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".EXT"s});
30099543e4SBrad Bishop }
31099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testSingleNoMatchNoModify)32099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testSingleNoMatchNoModify)
33099543e4SBrad Bishop {
34099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
35099543e4SBrad Bishop         {"system-bar"s, {".EXT"s}},
36099543e4SBrad Bishop     }};
37099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s},
38099543e4SBrad Bishop         extensions{"foo"s};
39099543e4SBrad Bishop     auto found =
40099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
41099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
42099543e4SBrad Bishop     EXPECT_FALSE(found);
43099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{"foo"s});
44099543e4SBrad Bishop }
45099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMatchModify)46099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMatchModify)
47099543e4SBrad Bishop {
48099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
49099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
50099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
51099543e4SBrad Bishop     }};
52099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s},
53099543e4SBrad Bishop         extensions{"foo"s};
54099543e4SBrad Bishop     auto found =
55099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
56099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
57099543e4SBrad Bishop     EXPECT_TRUE(found);
58099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".FOO"s});
59099543e4SBrad Bishop }
60099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testEmpty)61099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testEmpty)
62099543e4SBrad Bishop {
63099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap;
64099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s},
65099543e4SBrad Bishop         extensions{"foo"s};
66099543e4SBrad Bishop     auto found =
67099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
68099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
69099543e4SBrad Bishop     EXPECT_FALSE(found);
70099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{"foo"s});
71099543e4SBrad Bishop }
72099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testEmptyEmpty)73099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testEmptyEmpty)
74099543e4SBrad Bishop {
75099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap;
76099543e4SBrad Bishop     std::vector<std::string> compatibleSystem, extensions{"foo"s};
77099543e4SBrad Bishop     auto found =
78099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
79099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
80099543e4SBrad Bishop     EXPECT_FALSE(found);
81099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{"foo"s});
82099543e4SBrad Bishop }
83099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMatchMultiCompat)84099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMatchMultiCompat)
85099543e4SBrad Bishop {
86099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
87099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
88099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
89099543e4SBrad Bishop     }};
90099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s, "system"},
91099543e4SBrad Bishop         extensions;
92099543e4SBrad Bishop     auto found =
93099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
94099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
95099543e4SBrad Bishop     EXPECT_TRUE(found);
96099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".FOO"s});
97099543e4SBrad Bishop }
98099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMultiMatchMultiCompat)99099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMultiMatchMultiCompat)
100099543e4SBrad Bishop {
101099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
102099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
103099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
104099543e4SBrad Bishop     }};
105099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s, "system-bar"},
106099543e4SBrad Bishop         extensions;
107099543e4SBrad Bishop     auto found =
108099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
109099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
110099543e4SBrad Bishop     EXPECT_TRUE(found);
111099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".FOO"s});
112099543e4SBrad Bishop }
113099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMultiMatchMultiCompat2)114099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMultiMatchMultiCompat2)
115099543e4SBrad Bishop {
116099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
117099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
118099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
119099543e4SBrad Bishop     }};
120099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-foo"s, "system-bar"},
121099543e4SBrad Bishop         extensions;
122099543e4SBrad Bishop     auto found =
123099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
124099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
125099543e4SBrad Bishop     EXPECT_TRUE(found);
126099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".FOO"s});
127099543e4SBrad Bishop }
128099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMultiMatchMultiCompat3)129099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMultiMatchMultiCompat3)
130099543e4SBrad Bishop {
131099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
132099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
133099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
134099543e4SBrad Bishop     }};
135099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-bar", "system-foo"s},
136099543e4SBrad Bishop         extensions;
137099543e4SBrad Bishop     auto found =
138099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
139099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
140099543e4SBrad Bishop     EXPECT_TRUE(found);
141099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".BAR"s});
142099543e4SBrad Bishop }
143099543e4SBrad Bishop 
TEST(GetExtensionsForIbmCompatibleSystem,testMultiMatchMultiCompat4)144099543e4SBrad Bishop TEST(GetExtensionsForIbmCompatibleSystem, testMultiMatchMultiCompat4)
145099543e4SBrad Bishop {
146099543e4SBrad Bishop     std::map<std::string, std::vector<std::string>> extensionMap{{
147099543e4SBrad Bishop         {"system-foo"s, {".FOO"s}},
148099543e4SBrad Bishop         {"system-bar"s, {".BAR"s}},
149099543e4SBrad Bishop     }};
150099543e4SBrad Bishop     std::vector<std::string> compatibleSystem{"system-bar", "system-foo"s},
151099543e4SBrad Bishop         extensions;
152099543e4SBrad Bishop     auto found =
153099543e4SBrad Bishop         functions::process_hostfirmware::getExtensionsForIbmCompatibleSystem(
154099543e4SBrad Bishop             extensionMap, compatibleSystem, extensions);
155099543e4SBrad Bishop     EXPECT_TRUE(found);
156099543e4SBrad Bishop     EXPECT_EQ(extensions, std::vector<std::string>{".BAR"s});
157099543e4SBrad Bishop }
158099543e4SBrad Bishop 
TEST(MaybeCall,noMatch)159099543e4SBrad Bishop TEST(MaybeCall, noMatch)
160099543e4SBrad Bishop {
161099543e4SBrad Bishop     bool called = false;
162099543e4SBrad Bishop     auto callback = [&called](const auto&) { called = true; };
163099543e4SBrad Bishop     std::map<std::string,
164099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
165099543e4SBrad Bishop         interfaces{{
166099543e4SBrad Bishop             {"foo"s, {{"bar"s, std::vector<std::string>{"foo"s}}}},
167099543e4SBrad Bishop         }};
168099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
169099543e4SBrad Bishop         interfaces, std::move(callback));
170099543e4SBrad Bishop     EXPECT_FALSE(found);
171099543e4SBrad Bishop     EXPECT_FALSE(called);
172099543e4SBrad Bishop }
173099543e4SBrad Bishop 
TEST(MaybeCall,match)174099543e4SBrad Bishop TEST(MaybeCall, match)
175099543e4SBrad Bishop {
176099543e4SBrad Bishop     bool called = false;
177099543e4SBrad Bishop     std::vector<std::string> sys;
178099543e4SBrad Bishop     auto callback = [&called, &sys](const auto& system) {
179099543e4SBrad Bishop         sys = system;
180099543e4SBrad Bishop         called = true;
181099543e4SBrad Bishop     };
182099543e4SBrad Bishop     std::map<std::string,
183099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
184099543e4SBrad Bishop         interfaces{{
185*749bdcc9SAdriana Kobylak             {"xyz.openbmc_project.Inventory.Decorator.Compatible"s,
186099543e4SBrad Bishop              {{"Names"s, std::vector<std::string>{"foo"s}}}},
187099543e4SBrad Bishop         }};
188099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
189099543e4SBrad Bishop         interfaces, std::move(callback));
190099543e4SBrad Bishop     EXPECT_TRUE(found);
191099543e4SBrad Bishop     EXPECT_TRUE(called);
192099543e4SBrad Bishop     EXPECT_EQ(sys, std::vector<std::string>{"foo"s});
193099543e4SBrad Bishop }
194099543e4SBrad Bishop 
TEST(MaybeCall,missingNames)195099543e4SBrad Bishop TEST(MaybeCall, missingNames)
196099543e4SBrad Bishop {
197099543e4SBrad Bishop     bool called = false;
198099543e4SBrad Bishop     auto callback = [&called](const auto&) { called = true; };
199099543e4SBrad Bishop     std::map<std::string,
200099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
201099543e4SBrad Bishop         interfaces{{
202*749bdcc9SAdriana Kobylak             {"xyz.openbmc_project.Inventory.Decorator.Compatible"s, {}},
203099543e4SBrad Bishop         }};
204099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
205099543e4SBrad Bishop         interfaces, std::move(callback));
206099543e4SBrad Bishop     EXPECT_TRUE(found);
207099543e4SBrad Bishop     EXPECT_FALSE(called);
208099543e4SBrad Bishop }
209099543e4SBrad Bishop 
TEST(MaybeCall,emptyCallbackFound)210099543e4SBrad Bishop TEST(MaybeCall, emptyCallbackFound)
211099543e4SBrad Bishop {
212099543e4SBrad Bishop     std::map<std::string,
213099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
214099543e4SBrad Bishop         interfaces{{
215*749bdcc9SAdriana Kobylak             {"xyz.openbmc_project.Inventory.Decorator.Compatible"s,
216099543e4SBrad Bishop              {{"Names"s, std::vector<std::string>{"foo"s}}}},
217099543e4SBrad Bishop         }};
218099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
219099543e4SBrad Bishop         interfaces, std::function<void(std::vector<std::string>)>());
220099543e4SBrad Bishop     EXPECT_TRUE(found);
221099543e4SBrad Bishop }
222099543e4SBrad Bishop 
TEST(MaybeCall,emptyCallbackNotFound)223099543e4SBrad Bishop TEST(MaybeCall, emptyCallbackNotFound)
224099543e4SBrad Bishop {
225099543e4SBrad Bishop     std::map<std::string,
226099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
227099543e4SBrad Bishop         interfaces{{
228099543e4SBrad Bishop             {"foo"s, {{"Names"s, std::vector<std::string>{"foo"s}}}},
229099543e4SBrad Bishop         }};
230099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
231099543e4SBrad Bishop         interfaces, std::function<void(std::vector<std::string>)>());
232099543e4SBrad Bishop     EXPECT_FALSE(found);
233099543e4SBrad Bishop }
234099543e4SBrad Bishop 
TEST(MaybeCall,emptyInterfaces)235099543e4SBrad Bishop TEST(MaybeCall, emptyInterfaces)
236099543e4SBrad Bishop {
237099543e4SBrad Bishop     bool called = false;
238099543e4SBrad Bishop     auto callback = [&called](const auto&) { called = true; };
239099543e4SBrad Bishop     std::map<std::string,
240099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
241099543e4SBrad Bishop         interfaces;
242099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
243099543e4SBrad Bishop         interfaces, std::move(callback));
244099543e4SBrad Bishop     EXPECT_FALSE(found);
245099543e4SBrad Bishop     EXPECT_FALSE(called);
246099543e4SBrad Bishop }
247099543e4SBrad Bishop 
TEST(MaybeCall,emptyInterfacesEmptyCallback)248099543e4SBrad Bishop TEST(MaybeCall, emptyInterfacesEmptyCallback)
249099543e4SBrad Bishop {
250099543e4SBrad Bishop     std::map<std::string,
251099543e4SBrad Bishop              std::map<std::string, std::variant<std::vector<std::string>>>>
252099543e4SBrad Bishop         interfaces;
253099543e4SBrad Bishop     auto found = functions::process_hostfirmware::maybeCall(
254099543e4SBrad Bishop         interfaces, std::function<void(std::vector<std::string>)>());
255099543e4SBrad Bishop     EXPECT_FALSE(found);
256099543e4SBrad Bishop }
257099543e4SBrad Bishop 
TEST(WriteLink,testLinkNoDelete)258099543e4SBrad Bishop TEST(WriteLink, testLinkNoDelete)
259099543e4SBrad Bishop {
260099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
261099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
262099543e4SBrad Bishop     bool called = false;
263099543e4SBrad Bishop     auto callback = [&called](const auto&, auto&) { called = true; };
264099543e4SBrad Bishop     std::filesystem::path linkPath = workdir / "link";
265099543e4SBrad Bishop     std::filesystem::path targetPath = workdir / "target";
266099543e4SBrad Bishop     std::ofstream link{linkPath};
267099543e4SBrad Bishop     functions::process_hostfirmware::writeLink(linkPath.filename(), targetPath,
268099543e4SBrad Bishop                                                callback);
269099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
270099543e4SBrad Bishop     EXPECT_FALSE(called);
271099543e4SBrad Bishop }
272099543e4SBrad Bishop 
TEST(WriteLink,testLinkDelete)273099543e4SBrad Bishop TEST(WriteLink, testLinkDelete)
274099543e4SBrad Bishop {
275099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
276099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
277099543e4SBrad Bishop     bool called = false;
278099543e4SBrad Bishop     auto callback = [&called](const auto&, auto&) { called = true; };
279099543e4SBrad Bishop     auto linkPath = workdir / "link";
280099543e4SBrad Bishop     auto targetPath = workdir / "target";
281099543e4SBrad Bishop     std::ofstream link{linkPath}, target{targetPath};
282099543e4SBrad Bishop     functions::process_hostfirmware::writeLink(linkPath.filename(), targetPath,
283099543e4SBrad Bishop                                                callback);
284099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
285099543e4SBrad Bishop     EXPECT_FALSE(called);
286099543e4SBrad Bishop }
287099543e4SBrad Bishop 
TEST(WriteLink,testLinkFailDeleteDir)288099543e4SBrad Bishop TEST(WriteLink, testLinkFailDeleteDir)
289099543e4SBrad Bishop {
290099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
291099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
292099543e4SBrad Bishop     std::error_code ec;
293099543e4SBrad Bishop     std::filesystem::path callbackPath;
294099543e4SBrad Bishop     auto callback = [&ec, &callbackPath](const auto& p, auto& _ec) {
295099543e4SBrad Bishop         ec = _ec;
296099543e4SBrad Bishop         callbackPath = p;
297099543e4SBrad Bishop     };
298099543e4SBrad Bishop     auto targetPath = workdir / "target";
299099543e4SBrad Bishop     std::filesystem::create_directory(targetPath);
300099543e4SBrad Bishop     auto linkPath = workdir / "link";
301099543e4SBrad Bishop     auto filePath = targetPath / "file";
302099543e4SBrad Bishop     std::ofstream link{linkPath}, file{filePath};
303099543e4SBrad Bishop     functions::process_hostfirmware::writeLink(linkPath.filename(), targetPath,
304099543e4SBrad Bishop                                                callback);
305099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
306099543e4SBrad Bishop     EXPECT_EQ(ec.value(), ENOTEMPTY);
307099543e4SBrad Bishop     EXPECT_EQ(callbackPath, targetPath);
308099543e4SBrad Bishop }
309099543e4SBrad Bishop 
TEST(WriteLink,testLinkPathNotExist)310099543e4SBrad Bishop TEST(WriteLink, testLinkPathNotExist)
311099543e4SBrad Bishop {
312099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
313099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
314099543e4SBrad Bishop     std::error_code ec;
315099543e4SBrad Bishop     std::filesystem::path callbackPath;
316099543e4SBrad Bishop     auto callback = [&ec, &callbackPath](const auto& p, auto& _ec) {
317099543e4SBrad Bishop         ec = _ec;
318099543e4SBrad Bishop         callbackPath = p;
319099543e4SBrad Bishop     };
320099543e4SBrad Bishop     auto linkPath = workdir / "baz";
321099543e4SBrad Bishop     auto targetPath = workdir / "foo/bar/foo";
322099543e4SBrad Bishop     functions::process_hostfirmware::writeLink(linkPath.filename(), targetPath,
323099543e4SBrad Bishop                                                callback);
324099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
325099543e4SBrad Bishop     EXPECT_EQ(ec.value(), ENOENT);
326099543e4SBrad Bishop     EXPECT_EQ(callbackPath, targetPath);
327099543e4SBrad Bishop }
328099543e4SBrad Bishop 
TEST(FindLinks,testNoLinks)329099543e4SBrad Bishop TEST(FindLinks, testNoLinks)
330099543e4SBrad Bishop {
331099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
332099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
333099543e4SBrad Bishop 
334099543e4SBrad Bishop     bool callbackCalled = false, errorCallbackCalled = false;
335099543e4SBrad Bishop     auto callback = [&callbackCalled](const auto&, const auto&, const auto&) {
336099543e4SBrad Bishop         callbackCalled = true;
337099543e4SBrad Bishop     };
338099543e4SBrad Bishop     auto errorCallback = [&errorCallbackCalled](const auto&, auto&) {
339099543e4SBrad Bishop         errorCallbackCalled = true;
340099543e4SBrad Bishop     };
341099543e4SBrad Bishop 
342099543e4SBrad Bishop     std::vector<std::string> extensions;
343099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(workdir, extensions,
344099543e4SBrad Bishop                                                errorCallback, callback);
345099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
346099543e4SBrad Bishop     EXPECT_FALSE(errorCallbackCalled);
347099543e4SBrad Bishop     EXPECT_FALSE(callbackCalled);
348099543e4SBrad Bishop }
349099543e4SBrad Bishop 
TEST(FindLinks,testOneFound)350099543e4SBrad Bishop TEST(FindLinks, testOneFound)
351099543e4SBrad Bishop {
352099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
353099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
354099543e4SBrad Bishop     std::filesystem::path callbackPath, callbackLink;
355099543e4SBrad Bishop 
356099543e4SBrad Bishop     bool errorCallbackCalled = false;
357099543e4SBrad Bishop     auto callback = [&callbackPath, &callbackLink](
358099543e4SBrad Bishop                         const auto& p1, const auto& p2, const auto&) {
359099543e4SBrad Bishop         callbackPath = p1;
360099543e4SBrad Bishop         callbackLink = p2;
361099543e4SBrad Bishop     };
362099543e4SBrad Bishop     auto errorCallback = [&errorCallbackCalled](const auto&, auto&) {
363099543e4SBrad Bishop         errorCallbackCalled = true;
364099543e4SBrad Bishop     };
365099543e4SBrad Bishop 
366099543e4SBrad Bishop     auto filePath = workdir / "foo.foo";
367099543e4SBrad Bishop     std::ofstream file{filePath};
368099543e4SBrad Bishop     std::vector<std::string> extensions{".foo"s};
369099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(workdir, extensions,
370099543e4SBrad Bishop                                                errorCallback, callback);
371099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
372099543e4SBrad Bishop     EXPECT_FALSE(errorCallbackCalled);
373099543e4SBrad Bishop     EXPECT_EQ(callbackLink, workdir / "foo");
374099543e4SBrad Bishop     EXPECT_EQ(callbackPath, filePath.filename());
375099543e4SBrad Bishop }
376099543e4SBrad Bishop 
TEST(FindLinks,testNoExtensions)377099543e4SBrad Bishop TEST(FindLinks, testNoExtensions)
378099543e4SBrad Bishop {
379099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
380099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
381099543e4SBrad Bishop     std::filesystem::path callbackPath, callbackLink;
382099543e4SBrad Bishop 
383099543e4SBrad Bishop     bool errorCallbackCalled = false, callbackCalled = false;
384099543e4SBrad Bishop     auto callback = [&callbackCalled](const auto&, const auto&, const auto&) {
385099543e4SBrad Bishop         callbackCalled = true;
386099543e4SBrad Bishop     };
387099543e4SBrad Bishop     auto errorCallback = [&errorCallbackCalled](const auto&, auto&) {
388099543e4SBrad Bishop         errorCallbackCalled = true;
389099543e4SBrad Bishop     };
390099543e4SBrad Bishop 
391099543e4SBrad Bishop     auto filePath = workdir / "foo.foo";
392099543e4SBrad Bishop     std::ofstream file{filePath};
393099543e4SBrad Bishop     std::vector<std::string> extensions;
394099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(workdir, extensions,
395099543e4SBrad Bishop                                                errorCallback, callback);
396099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
397099543e4SBrad Bishop     EXPECT_FALSE(errorCallbackCalled);
398099543e4SBrad Bishop     EXPECT_FALSE(callbackCalled);
399099543e4SBrad Bishop }
400099543e4SBrad Bishop 
TEST(FindLinks,testEnoent)401099543e4SBrad Bishop TEST(FindLinks, testEnoent)
402099543e4SBrad Bishop {
403099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
404099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
405099543e4SBrad Bishop 
406099543e4SBrad Bishop     std::error_code ec;
407099543e4SBrad Bishop     bool called = false;
408099543e4SBrad Bishop     std::filesystem::path callbackPath;
409099543e4SBrad Bishop     auto callback = [&called](const auto&, const auto&, const auto&) {
410099543e4SBrad Bishop         called = true;
411099543e4SBrad Bishop     };
412099543e4SBrad Bishop     auto errorCallback = [&ec, &callbackPath](const auto& p, auto& _ec) {
413099543e4SBrad Bishop         ec = _ec;
414099543e4SBrad Bishop         callbackPath = p;
415099543e4SBrad Bishop     };
416099543e4SBrad Bishop 
417099543e4SBrad Bishop     std::vector<std::string> extensions;
418099543e4SBrad Bishop     auto dir = workdir / "baz";
419099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(dir, extensions, errorCallback,
420099543e4SBrad Bishop                                                callback);
421099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
422099543e4SBrad Bishop     EXPECT_EQ(ec.value(), ENOENT);
423099543e4SBrad Bishop     EXPECT_EQ(callbackPath, dir);
424099543e4SBrad Bishop     EXPECT_FALSE(called);
425099543e4SBrad Bishop }
426099543e4SBrad Bishop 
TEST(FindLinks,testEmptyCallback)427099543e4SBrad Bishop TEST(FindLinks, testEmptyCallback)
428099543e4SBrad Bishop {
429099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
430099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
431099543e4SBrad Bishop 
432099543e4SBrad Bishop     bool called = false;
433099543e4SBrad Bishop     std::filesystem::path callbackPath;
434099543e4SBrad Bishop     auto errorCallback = [&called](const auto&, auto&) { called = true; };
435099543e4SBrad Bishop 
436099543e4SBrad Bishop     auto filePath = workdir / "foo.foo";
437099543e4SBrad Bishop     std::ofstream file{filePath};
438099543e4SBrad Bishop 
439099543e4SBrad Bishop     std::vector<std::string> extensions{".foo"s};
440099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(
441099543e4SBrad Bishop         workdir, extensions, errorCallback,
442099543e4SBrad Bishop         functions::process_hostfirmware::LinkCallbackType());
443099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
444099543e4SBrad Bishop     EXPECT_FALSE(called);
445099543e4SBrad Bishop     EXPECT_NO_THROW();
446099543e4SBrad Bishop }
447099543e4SBrad Bishop 
TEST(FindLinks,testEmptyErrorCallback)448099543e4SBrad Bishop TEST(FindLinks, testEmptyErrorCallback)
449099543e4SBrad Bishop {
450099543e4SBrad Bishop     std::array<char, 15> tmpl{"/tmp/tmpXXXXXX"};
451099543e4SBrad Bishop     std::filesystem::path workdir = mkdtemp(&tmpl[0]);
452099543e4SBrad Bishop 
453099543e4SBrad Bishop     bool called = false;
454099543e4SBrad Bishop     auto callback = [&called](const auto&, const auto&, const auto&) {
455099543e4SBrad Bishop         called = true;
456099543e4SBrad Bishop     };
457099543e4SBrad Bishop 
458099543e4SBrad Bishop     std::vector<std::string> extensions;
459099543e4SBrad Bishop     auto dir = workdir / "baz";
460099543e4SBrad Bishop     functions::process_hostfirmware::findLinks(
461099543e4SBrad Bishop         dir, extensions, functions::process_hostfirmware::ErrorCallbackType(),
462099543e4SBrad Bishop         callback);
463099543e4SBrad Bishop     std::filesystem::remove_all(workdir);
464099543e4SBrad Bishop     EXPECT_FALSE(called);
465099543e4SBrad Bishop     EXPECT_NO_THROW();
466099543e4SBrad Bishop }
467