blob: 6046382d99e835e23ebde95560053ff68dc43ea6 [file] [log] [blame]
Shawn McCarneyde5434d2024-05-22 14:07:44 -05001/**
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
25using namespace phosphor::power::util;
26namespace fs = std::filesystem;
27
28TEST(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
44TEST(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
65TEST(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
Jayanth Othayothb93d6eb2025-06-08 07:18:10 -0500113// This is undefined behavior in C++, but suppress the warning
114// to observe how the class handles it.
115#ifdef __clang__
116#pragma clang diagnostic push
117#pragma clang diagnostic ignored "-Wself-move"
118#endif
Shawn McCarneyde5434d2024-05-22 14:07:44 -0500119 // Try to move object into itself; should do nothing
120 subdirectory = static_cast<TemporarySubDirectory&&>(subdirectory);
Jayanth Othayothb93d6eb2025-06-08 07:18:10 -0500121#ifdef __clang__
122#pragma clang diagnostic pop
123#endif
Shawn McCarneyde5434d2024-05-22 14:07:44 -0500124
125 // Verify object still owns same subdirectory and subdirectory exists
126 EXPECT_EQ(subdirectory.getPath(), path);
127 EXPECT_TRUE(fs::exists(path));
128 }
129
130 // Test where fails: Cannot delete subdirectory
131 {
132 // Create first object and verify subdirectory exists
133 TemporarySubDirectory subdirectory1{};
134 EXPECT_FALSE(subdirectory1.getPath().empty());
135 EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
136
137 // Save path to first subdirectory
138 fs::path path1 = subdirectory1.getPath();
139
140 // Create second object and verify subdirectory exists
141 TemporarySubDirectory subdirectory2{};
142 EXPECT_FALSE(subdirectory2.getPath().empty());
143 EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
144
145 // Save path to second subdirectory
146 fs::path path2 = subdirectory2.getPath();
147
148 // Verify temporary subdirectories are different
149 EXPECT_NE(path1, path2);
150
151 // Change second subdirectory to unreadable so it cannot be removed
152 fs::permissions(path2, fs::perms::none);
153
154 try
155 {
156 // Try to move first object into the second; should throw exception
157 subdirectory2 = std::move(subdirectory1);
158 ADD_FAILURE() << "Should not have reached this line.";
159 }
160 catch (const std::exception& e)
161 {
162 // This is expected. Exception message will vary.
163 }
164
165 // Change second subdirectory to readable/writable so it can be removed
166 fs::permissions(path2, fs::perms::owner_all);
167
168 // Verify first object has not changed and first subdirectory exists
169 EXPECT_EQ(subdirectory1.getPath(), path1);
170 EXPECT_TRUE(fs::exists(path1));
171
172 // Verify second object has not changed and second subdirectory exists
173 EXPECT_EQ(subdirectory2.getPath(), path2);
174 EXPECT_TRUE(fs::exists(path2));
175 }
176}
177
178TEST(TemporarySubDirectoryTests, Destructor)
179{
180 // Test where works: Subdirectory is deleted
181 {
182 fs::path path{};
183 {
184 TemporarySubDirectory subdirectory{};
185 path = subdirectory.getPath();
186 EXPECT_TRUE(fs::exists(path));
187 }
188 EXPECT_FALSE(fs::exists(path));
189 }
190
191 // Test where works: Subdirectory was already deleted
192 {
193 fs::path path{};
194 {
195 TemporarySubDirectory subdirectory{};
196 path = subdirectory.getPath();
197 EXPECT_TRUE(fs::exists(path));
198 subdirectory.remove();
199 EXPECT_FALSE(fs::exists(path));
200 }
201 EXPECT_FALSE(fs::exists(path));
202 }
203
204 // Test where fails: Cannot delete subdirectory: No exception thrown
205 {
206 fs::path path{};
207 try
208 {
209 TemporarySubDirectory subdirectory{};
210 path = subdirectory.getPath();
211 EXPECT_TRUE(fs::exists(path));
212
213 // Change subdirectory to unreadable so it cannot be removed
214 fs::permissions(path, fs::perms::none);
215 }
216 catch (...)
217 {
218 ADD_FAILURE() << "Should not have caught exception.";
219 }
220
221 // Change subdirectory to readable/writable so it can be removed
222 fs::permissions(path, fs::perms::owner_all);
223
224 // Subdirectory should still exist
225 EXPECT_TRUE(fs::exists(path));
226
227 // Delete subdirectory
228 fs::remove_all(path);
229 }
230}
231
232TEST(TemporarySubDirectoryTests, Remove)
233{
234 // Test where works
235 {
236 // Create object and verify subdirectory exists
237 TemporarySubDirectory subdirectory{};
238 EXPECT_FALSE(subdirectory.getPath().empty());
239 EXPECT_TRUE(fs::exists(subdirectory.getPath()));
240
241 // Save path to subdirectory
242 fs::path path = subdirectory.getPath();
243
244 // Delete subdirectory
245 subdirectory.remove();
246
247 // Verify path is cleared and subdirectory does not exist
248 EXPECT_TRUE(subdirectory.getPath().empty());
249 EXPECT_FALSE(fs::exists(path));
250
251 // Delete subdirectory again; should do nothing
252 subdirectory.remove();
253 EXPECT_TRUE(subdirectory.getPath().empty());
254 EXPECT_FALSE(fs::exists(path));
255 }
256
257 // Test where fails
258 {
259 // Create object and verify subdirectory exists
260 TemporarySubDirectory subdirectory{};
261 EXPECT_FALSE(subdirectory.getPath().empty());
262 EXPECT_TRUE(fs::exists(subdirectory.getPath()));
263
264 // Save path to subdirectory
265 fs::path path = subdirectory.getPath();
266
267 // Change subdirectory to unreadable so it cannot be removed
268 fs::permissions(path, fs::perms::none);
269
270 try
271 {
272 // Try to delete subdirectory; should fail with exception
273 subdirectory.remove();
274 ADD_FAILURE() << "Should not have reached this line.";
275 }
276 catch (const std::exception& e)
277 {
278 // This is expected. Exception message will vary.
279 }
280
281 // Change subdirectory to readable/writable so it can be deleted by
282 // destructor
283 fs::permissions(path, fs::perms::owner_all);
284 }
285}
286
287TEST(TemporarySubDirectoryTests, GetPath)
288{
289 TemporarySubDirectory subdirectory{};
290 EXPECT_FALSE(subdirectory.getPath().empty());
291 EXPECT_EQ(subdirectory.getPath().parent_path(), "/tmp");
292 EXPECT_TRUE(fs::exists(subdirectory.getPath()));
293}