1*de5434d8SShawn McCarney /**
2*de5434d8SShawn McCarney * Copyright © 2024 IBM Corporation
3*de5434d8SShawn McCarney *
4*de5434d8SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License");
5*de5434d8SShawn McCarney * you may not use this file except in compliance with the License.
6*de5434d8SShawn McCarney * You may obtain a copy of the License at
7*de5434d8SShawn McCarney *
8*de5434d8SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0
9*de5434d8SShawn McCarney *
10*de5434d8SShawn McCarney * Unless required by applicable law or agreed to in writing, software
11*de5434d8SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS,
12*de5434d8SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*de5434d8SShawn McCarney * See the License for the specific language governing permissions and
14*de5434d8SShawn McCarney * limitations under the License.
15*de5434d8SShawn McCarney */
16*de5434d8SShawn McCarney #include "temporary_subdirectory.hpp"
17*de5434d8SShawn McCarney
18*de5434d8SShawn McCarney #include <filesystem>
19*de5434d8SShawn McCarney #include <fstream>
20*de5434d8SShawn McCarney #include <string>
21*de5434d8SShawn McCarney #include <utility>
22*de5434d8SShawn McCarney
23*de5434d8SShawn McCarney #include <gtest/gtest.h>
24*de5434d8SShawn McCarney
25*de5434d8SShawn McCarney using namespace phosphor::power::util;
26*de5434d8SShawn McCarney namespace fs = std::filesystem;
27*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,DefaultConstructor)28*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, DefaultConstructor)
29*de5434d8SShawn McCarney {
30*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
31*de5434d8SShawn McCarney
32*de5434d8SShawn McCarney fs::path path = subdirectory.getPath();
33*de5434d8SShawn McCarney EXPECT_FALSE(path.empty());
34*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
35*de5434d8SShawn McCarney EXPECT_TRUE(fs::is_directory(path));
36*de5434d8SShawn McCarney
37*de5434d8SShawn McCarney fs::path parentDir = path.parent_path();
38*de5434d8SShawn McCarney EXPECT_EQ(parentDir, "/tmp");
39*de5434d8SShawn McCarney
40*de5434d8SShawn McCarney std::string baseName = path.filename();
41*de5434d8SShawn McCarney EXPECT_TRUE(baseName.starts_with("phosphor-power-"));
42*de5434d8SShawn McCarney }
43*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,MoveConstructor)44*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, MoveConstructor)
45*de5434d8SShawn McCarney {
46*de5434d8SShawn McCarney // Create first object and verify subdirectory exists
47*de5434d8SShawn McCarney TemporarySubDirectory subdirectory1{};
48*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory1.getPath().empty());
49*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
50*de5434d8SShawn McCarney
51*de5434d8SShawn McCarney // Save path to subdirectory
52*de5434d8SShawn McCarney fs::path path = subdirectory1.getPath();
53*de5434d8SShawn McCarney
54*de5434d8SShawn McCarney // Create second object by moving first object
55*de5434d8SShawn McCarney TemporarySubDirectory subdirectory2{std::move(subdirectory1)};
56*de5434d8SShawn McCarney
57*de5434d8SShawn McCarney // Verify first object now has an empty path
58*de5434d8SShawn McCarney EXPECT_TRUE(subdirectory1.getPath().empty());
59*de5434d8SShawn McCarney
60*de5434d8SShawn McCarney // Verify second object now owns same subdirectory and subdirectory exists
61*de5434d8SShawn McCarney EXPECT_EQ(subdirectory2.getPath(), path);
62*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
63*de5434d8SShawn McCarney }
64*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,MoveAssignmentOperator)65*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, MoveAssignmentOperator)
66*de5434d8SShawn McCarney {
67*de5434d8SShawn McCarney // Test where works: object is moved
68*de5434d8SShawn McCarney {
69*de5434d8SShawn McCarney // Create first object and verify subdirectory exists
70*de5434d8SShawn McCarney TemporarySubDirectory subdirectory1{};
71*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory1.getPath().empty());
72*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
73*de5434d8SShawn McCarney
74*de5434d8SShawn McCarney // Save path to first subdirectory
75*de5434d8SShawn McCarney fs::path path1 = subdirectory1.getPath();
76*de5434d8SShawn McCarney
77*de5434d8SShawn McCarney // Create second object and verify subdirectory exists
78*de5434d8SShawn McCarney TemporarySubDirectory subdirectory2{};
79*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory2.getPath().empty());
80*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
81*de5434d8SShawn McCarney
82*de5434d8SShawn McCarney // Save path to second subdirectory
83*de5434d8SShawn McCarney fs::path path2 = subdirectory2.getPath();
84*de5434d8SShawn McCarney
85*de5434d8SShawn McCarney // Verify temporary subdirectories are different
86*de5434d8SShawn McCarney EXPECT_NE(path1, path2);
87*de5434d8SShawn McCarney
88*de5434d8SShawn McCarney // Move first object into the second
89*de5434d8SShawn McCarney subdirectory2 = std::move(subdirectory1);
90*de5434d8SShawn McCarney
91*de5434d8SShawn McCarney // Verify first object now has an empty path
92*de5434d8SShawn McCarney EXPECT_TRUE(subdirectory1.getPath().empty());
93*de5434d8SShawn McCarney
94*de5434d8SShawn McCarney // Verify second object now owns first subdirectory and subdirectory
95*de5434d8SShawn McCarney // exists
96*de5434d8SShawn McCarney EXPECT_EQ(subdirectory2.getPath(), path1);
97*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path1));
98*de5434d8SShawn McCarney
99*de5434d8SShawn McCarney // Verify second subdirectory was deleted
100*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path2));
101*de5434d8SShawn McCarney }
102*de5434d8SShawn McCarney
103*de5434d8SShawn McCarney // Test where does nothing: object moved into itself
104*de5434d8SShawn McCarney {
105*de5434d8SShawn McCarney // Create object and verify subdirectory exists
106*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
107*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory.getPath().empty());
108*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory.getPath()));
109*de5434d8SShawn McCarney
110*de5434d8SShawn McCarney // Save path to subdirectory
111*de5434d8SShawn McCarney fs::path path = subdirectory.getPath();
112*de5434d8SShawn McCarney
113*de5434d8SShawn McCarney // Try to move object into itself; should do nothing
114*de5434d8SShawn McCarney subdirectory = static_cast<TemporarySubDirectory&&>(subdirectory);
115*de5434d8SShawn McCarney
116*de5434d8SShawn McCarney // Verify object still owns same subdirectory and subdirectory exists
117*de5434d8SShawn McCarney EXPECT_EQ(subdirectory.getPath(), path);
118*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
119*de5434d8SShawn McCarney }
120*de5434d8SShawn McCarney
121*de5434d8SShawn McCarney // Test where fails: Cannot delete subdirectory
122*de5434d8SShawn McCarney {
123*de5434d8SShawn McCarney // Create first object and verify subdirectory exists
124*de5434d8SShawn McCarney TemporarySubDirectory subdirectory1{};
125*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory1.getPath().empty());
126*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
127*de5434d8SShawn McCarney
128*de5434d8SShawn McCarney // Save path to first subdirectory
129*de5434d8SShawn McCarney fs::path path1 = subdirectory1.getPath();
130*de5434d8SShawn McCarney
131*de5434d8SShawn McCarney // Create second object and verify subdirectory exists
132*de5434d8SShawn McCarney TemporarySubDirectory subdirectory2{};
133*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory2.getPath().empty());
134*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
135*de5434d8SShawn McCarney
136*de5434d8SShawn McCarney // Save path to second subdirectory
137*de5434d8SShawn McCarney fs::path path2 = subdirectory2.getPath();
138*de5434d8SShawn McCarney
139*de5434d8SShawn McCarney // Verify temporary subdirectories are different
140*de5434d8SShawn McCarney EXPECT_NE(path1, path2);
141*de5434d8SShawn McCarney
142*de5434d8SShawn McCarney // Change second subdirectory to unreadable so it cannot be removed
143*de5434d8SShawn McCarney fs::permissions(path2, fs::perms::none);
144*de5434d8SShawn McCarney
145*de5434d8SShawn McCarney try
146*de5434d8SShawn McCarney {
147*de5434d8SShawn McCarney // Try to move first object into the second; should throw exception
148*de5434d8SShawn McCarney subdirectory2 = std::move(subdirectory1);
149*de5434d8SShawn McCarney ADD_FAILURE() << "Should not have reached this line.";
150*de5434d8SShawn McCarney }
151*de5434d8SShawn McCarney catch (const std::exception& e)
152*de5434d8SShawn McCarney {
153*de5434d8SShawn McCarney // This is expected. Exception message will vary.
154*de5434d8SShawn McCarney }
155*de5434d8SShawn McCarney
156*de5434d8SShawn McCarney // Change second subdirectory to readable/writable so it can be removed
157*de5434d8SShawn McCarney fs::permissions(path2, fs::perms::owner_all);
158*de5434d8SShawn McCarney
159*de5434d8SShawn McCarney // Verify first object has not changed and first subdirectory exists
160*de5434d8SShawn McCarney EXPECT_EQ(subdirectory1.getPath(), path1);
161*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path1));
162*de5434d8SShawn McCarney
163*de5434d8SShawn McCarney // Verify second object has not changed and second subdirectory exists
164*de5434d8SShawn McCarney EXPECT_EQ(subdirectory2.getPath(), path2);
165*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path2));
166*de5434d8SShawn McCarney }
167*de5434d8SShawn McCarney }
168*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,Destructor)169*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, Destructor)
170*de5434d8SShawn McCarney {
171*de5434d8SShawn McCarney // Test where works: Subdirectory is deleted
172*de5434d8SShawn McCarney {
173*de5434d8SShawn McCarney fs::path path{};
174*de5434d8SShawn McCarney {
175*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
176*de5434d8SShawn McCarney path = subdirectory.getPath();
177*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
178*de5434d8SShawn McCarney }
179*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path));
180*de5434d8SShawn McCarney }
181*de5434d8SShawn McCarney
182*de5434d8SShawn McCarney // Test where works: Subdirectory was already deleted
183*de5434d8SShawn McCarney {
184*de5434d8SShawn McCarney fs::path path{};
185*de5434d8SShawn McCarney {
186*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
187*de5434d8SShawn McCarney path = subdirectory.getPath();
188*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
189*de5434d8SShawn McCarney subdirectory.remove();
190*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path));
191*de5434d8SShawn McCarney }
192*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path));
193*de5434d8SShawn McCarney }
194*de5434d8SShawn McCarney
195*de5434d8SShawn McCarney // Test where fails: Cannot delete subdirectory: No exception thrown
196*de5434d8SShawn McCarney {
197*de5434d8SShawn McCarney fs::path path{};
198*de5434d8SShawn McCarney try
199*de5434d8SShawn McCarney {
200*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
201*de5434d8SShawn McCarney path = subdirectory.getPath();
202*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
203*de5434d8SShawn McCarney
204*de5434d8SShawn McCarney // Change subdirectory to unreadable so it cannot be removed
205*de5434d8SShawn McCarney fs::permissions(path, fs::perms::none);
206*de5434d8SShawn McCarney }
207*de5434d8SShawn McCarney catch (...)
208*de5434d8SShawn McCarney {
209*de5434d8SShawn McCarney ADD_FAILURE() << "Should not have caught exception.";
210*de5434d8SShawn McCarney }
211*de5434d8SShawn McCarney
212*de5434d8SShawn McCarney // Change subdirectory to readable/writable so it can be removed
213*de5434d8SShawn McCarney fs::permissions(path, fs::perms::owner_all);
214*de5434d8SShawn McCarney
215*de5434d8SShawn McCarney // Subdirectory should still exist
216*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(path));
217*de5434d8SShawn McCarney
218*de5434d8SShawn McCarney // Delete subdirectory
219*de5434d8SShawn McCarney fs::remove_all(path);
220*de5434d8SShawn McCarney }
221*de5434d8SShawn McCarney }
222*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,Remove)223*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, Remove)
224*de5434d8SShawn McCarney {
225*de5434d8SShawn McCarney // Test where works
226*de5434d8SShawn McCarney {
227*de5434d8SShawn McCarney // Create object and verify subdirectory exists
228*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
229*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory.getPath().empty());
230*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory.getPath()));
231*de5434d8SShawn McCarney
232*de5434d8SShawn McCarney // Save path to subdirectory
233*de5434d8SShawn McCarney fs::path path = subdirectory.getPath();
234*de5434d8SShawn McCarney
235*de5434d8SShawn McCarney // Delete subdirectory
236*de5434d8SShawn McCarney subdirectory.remove();
237*de5434d8SShawn McCarney
238*de5434d8SShawn McCarney // Verify path is cleared and subdirectory does not exist
239*de5434d8SShawn McCarney EXPECT_TRUE(subdirectory.getPath().empty());
240*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path));
241*de5434d8SShawn McCarney
242*de5434d8SShawn McCarney // Delete subdirectory again; should do nothing
243*de5434d8SShawn McCarney subdirectory.remove();
244*de5434d8SShawn McCarney EXPECT_TRUE(subdirectory.getPath().empty());
245*de5434d8SShawn McCarney EXPECT_FALSE(fs::exists(path));
246*de5434d8SShawn McCarney }
247*de5434d8SShawn McCarney
248*de5434d8SShawn McCarney // Test where fails
249*de5434d8SShawn McCarney {
250*de5434d8SShawn McCarney // Create object and verify subdirectory exists
251*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
252*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory.getPath().empty());
253*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory.getPath()));
254*de5434d8SShawn McCarney
255*de5434d8SShawn McCarney // Save path to subdirectory
256*de5434d8SShawn McCarney fs::path path = subdirectory.getPath();
257*de5434d8SShawn McCarney
258*de5434d8SShawn McCarney // Change subdirectory to unreadable so it cannot be removed
259*de5434d8SShawn McCarney fs::permissions(path, fs::perms::none);
260*de5434d8SShawn McCarney
261*de5434d8SShawn McCarney try
262*de5434d8SShawn McCarney {
263*de5434d8SShawn McCarney // Try to delete subdirectory; should fail with exception
264*de5434d8SShawn McCarney subdirectory.remove();
265*de5434d8SShawn McCarney ADD_FAILURE() << "Should not have reached this line.";
266*de5434d8SShawn McCarney }
267*de5434d8SShawn McCarney catch (const std::exception& e)
268*de5434d8SShawn McCarney {
269*de5434d8SShawn McCarney // This is expected. Exception message will vary.
270*de5434d8SShawn McCarney }
271*de5434d8SShawn McCarney
272*de5434d8SShawn McCarney // Change subdirectory to readable/writable so it can be deleted by
273*de5434d8SShawn McCarney // destructor
274*de5434d8SShawn McCarney fs::permissions(path, fs::perms::owner_all);
275*de5434d8SShawn McCarney }
276*de5434d8SShawn McCarney }
277*de5434d8SShawn McCarney
TEST(TemporarySubDirectoryTests,GetPath)278*de5434d8SShawn McCarney TEST(TemporarySubDirectoryTests, GetPath)
279*de5434d8SShawn McCarney {
280*de5434d8SShawn McCarney TemporarySubDirectory subdirectory{};
281*de5434d8SShawn McCarney EXPECT_FALSE(subdirectory.getPath().empty());
282*de5434d8SShawn McCarney EXPECT_EQ(subdirectory.getPath().parent_path(), "/tmp");
283*de5434d8SShawn McCarney EXPECT_TRUE(fs::exists(subdirectory.getPath()));
284*de5434d8SShawn McCarney }
285