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