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