blob: bbc9151b215f0d0119a25216e8b94d5e2b00aca5 [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2021 IBM Corporation
3
Jayanth Othayothbf54cbb2021-06-03 04:36:48 -05004#include "extensions/openpower-pels/temporary_file.hpp"
5
6#include <filesystem>
7#include <fstream>
8#include <string>
9#include <utility>
10
11#include <gtest/gtest.h>
12
13using namespace openpower::pels::util;
14namespace fs = std::filesystem;
15
16/**
17 * Modify the specified file so that fs::remove() can successfully delete it.
18 *
19 * Undo the modifications from an earlier call to makeFileUnRemovable().
20 *
21 * @param path path to the file
22 */
23inline void makeFileRemovable(const fs::path& path)
24{
25 // makeFileUnRemovable() creates a directory at the file path. Remove the
26 // directory and all of its contents.
27 fs::remove_all(path);
28
29 // Rename the file back to the original path to restore its contents
30 fs::path savePath{path.native() + ".save"};
31 fs::rename(savePath, path);
32}
33
34/**
35 * Modify the specified file so that fs::remove() fails with an exception.
36 *
37 * The file will be renamed and can be restored by calling makeFileRemovable().
38 *
39 * @param path path to the file
40 */
41inline void makeFileUnRemovable(const fs::path& path)
42{
43 // Rename the file to save its contents
44 fs::path savePath{path.native() + ".save"};
45 fs::rename(path, savePath);
46
47 // Create a directory at the original file path
48 fs::create_directory(path);
49
50 // Create a file within the directory. fs::remove() will throw an exception
51 // if the path is a non-empty directory.
52 std::ofstream childFile{path / "childFile"};
53}
54
55class TemporaryFileTests : public ::testing::Test
56{
57 protected:
58 void SetUp() override
59 {
60 // Create temporary file with some data
61 std::string buf{"FFDCDATA"};
62 uint32_t size = buf.size();
63 tmpFile = new TemporaryFile(buf.c_str(), size);
64
65 // Create temporary file with no data
66 std::string noData{""};
67 tmpFileNoData = new TemporaryFile(noData.c_str(), 0);
68 }
69
70 void TearDown() override
71 {
72 std::filesystem::remove_all(tmpFile->getPath());
73 delete tmpFile;
74
75 std::filesystem::remove_all(tmpFileNoData->getPath());
76 delete tmpFileNoData;
77 }
78
79 // temporary file with Data
80 TemporaryFile* tmpFile;
81
82 // temporary file with no data
83 TemporaryFile* tmpFileNoData;
84};
85
86TEST_F(TemporaryFileTests, DefaultConstructor)
87{
88 fs::path path = tmpFile->getPath();
89 EXPECT_FALSE(path.empty());
90 EXPECT_TRUE(fs::exists(path));
91 EXPECT_TRUE(fs::is_regular_file(path));
92
93 fs::path parentDir = path.parent_path();
94 EXPECT_EQ(parentDir, "/tmp");
95
96 std::string fileName = path.filename();
97 std::string namePrefix = "phosphor-logging-";
98 EXPECT_EQ(fileName.compare(0, namePrefix.size(), namePrefix), 0);
99}
100
101TEST_F(TemporaryFileTests, DefaultConstructorNoData)
102{
103 fs::path path = tmpFileNoData->getPath();
104 EXPECT_FALSE(path.empty());
105 EXPECT_TRUE(fs::exists(path));
106 EXPECT_TRUE(fs::is_regular_file(path));
107
108 fs::path parentDir = path.parent_path();
109 EXPECT_EQ(parentDir, "/tmp");
110
111 std::string fileName = path.filename();
112 std::string namePrefix = "phosphor-logging-";
113 EXPECT_EQ(fileName.compare(0, namePrefix.size(), namePrefix), 0);
114}
115
116TEST_F(TemporaryFileTests, MoveConstructor)
117{
118 // verify temporary file exists
119 EXPECT_FALSE(tmpFile->getPath().empty());
120 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
121
122 // Save path to temporary file
123 fs::path path = tmpFile->getPath();
124
125 // Create second TemporaryFile object by moving first object
126 TemporaryFile file{std::move(*tmpFile)};
127
128 // Verify first object now has an empty path
129 EXPECT_TRUE(tmpFile->getPath().empty());
130
131 // Verify second object now owns same temporary file and file exists
132 EXPECT_EQ(file.getPath(), path);
133 EXPECT_TRUE(fs::exists(file.getPath()));
134
135 // Delete file
136 std::filesystem::remove_all(file.getPath());
137}
138
139TEST_F(TemporaryFileTests, MoveAssignmentOperatorTest1)
140{
141 // Test where works: TemporaryFile object is moved
142 // verify temporary file exists
143 EXPECT_FALSE(tmpFile->getPath().empty());
144 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
145
146 // Save path to first temporary file
147 fs::path path1 = tmpFile->getPath();
148
149 // Verify second temporary file exists
150 EXPECT_FALSE(tmpFileNoData->getPath().empty());
151 EXPECT_TRUE(fs::exists(tmpFileNoData->getPath()));
152
153 // Save path to second temporary file
154 fs::path path2 = tmpFileNoData->getPath();
155
156 // Verify temporary files are different
157 EXPECT_NE(path1, path2);
158
159 // Move first object into the second
160 *tmpFileNoData = std::move(*tmpFile);
161
162 // Verify first object now has an empty path
163 EXPECT_TRUE(tmpFile->getPath().empty());
164
165 // Verify second object now owns first temporary file and file exists
166 EXPECT_EQ(tmpFileNoData->getPath(), path1);
167 EXPECT_TRUE(fs::exists(path1));
168
169 // Verify second temporary file was deleted
170 EXPECT_FALSE(fs::exists(path2));
171}
172
173TEST_F(TemporaryFileTests, MoveAssignmentOperatorTest2)
174{
175 // Test where does nothing: TemporaryFile object is moved into itself
176 // Verify temporary file exists
177 EXPECT_FALSE(tmpFile->getPath().empty());
178 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
179
180 // Save path to temporary file
181 fs::path path = tmpFile->getPath();
182
183 // Try to move object into itself; should do nothing
Matt Spinler81bc5612023-06-01 16:48:19 -0500184 *tmpFile = static_cast<TemporaryFile&&>(*tmpFile);
Jayanth Othayothbf54cbb2021-06-03 04:36:48 -0500185
186 // Verify object still owns same temporary file and file exists
187 EXPECT_EQ(tmpFile->getPath(), path);
188 EXPECT_TRUE(fs::exists(path));
189}
190
191TEST_F(TemporaryFileTests, MoveAssignmentOperatorTest3)
192{
193 // Test where fails: Cannot delete temporary file
194 // Verify temporary file exists
195 EXPECT_FALSE(tmpFile->getPath().empty());
196 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
197
198 // Save path to first temporary file
199 fs::path path1 = tmpFile->getPath();
200
201 // Verify temporary file exists
202 EXPECT_FALSE(tmpFileNoData->getPath().empty());
203 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
204
205 // Save path to second temporary file
206 fs::path path2 = tmpFileNoData->getPath();
207
208 // Verify temporary files are different
209 EXPECT_NE(path1, path2);
210
211 // Make second temporary file unremoveable
212 makeFileUnRemovable(path2);
213
214 try
215 {
216 // Try to move first object into the second; should throw exception
217 *tmpFileNoData = std::move(*tmpFile);
218 ADD_FAILURE() << "Should not have reached this line.";
219 }
220 catch (const std::exception& e)
221 {
222 // This is expected. Exception message will vary.
223 }
224
225 // Verify first object has not changed and first temporary file exists
226 EXPECT_EQ(tmpFile->getPath(), path1);
227 EXPECT_TRUE(fs::exists(path1));
228
229 // Verify second object has not changed and second temporary file exists
230 EXPECT_EQ(tmpFileNoData->getPath(), path2);
231 EXPECT_TRUE(fs::exists(path2));
232
233 // Make second temporary file removeable so destructor can delete it
234 makeFileRemovable(path2);
235}
236
237TEST_F(TemporaryFileTests, Destructor)
238{
239 // Test where works: Temporary file is not deleted
240 {
241 fs::path path{};
242 {
243 TemporaryFile file("", 0);
244 path = file.getPath();
245 EXPECT_TRUE(fs::exists(path));
246 }
247 EXPECT_TRUE(fs::exists(path));
248 fs::remove(path);
249 }
250
251 // Test where works: Temporary file was already deleted
252 {
253 fs::path path{};
254 {
255 TemporaryFile file("", 0);
256 path = file.getPath();
257 EXPECT_TRUE(fs::exists(path));
258 file.remove();
259 EXPECT_FALSE(fs::exists(path));
260 }
261 EXPECT_FALSE(fs::exists(path));
262 }
263
264 // Test where fails: Cannot delete temporary file: No exception thrown
265 {
266 fs::path path{};
267 try
268 {
269 TemporaryFile file("", 0);
270 path = file.getPath();
271 EXPECT_TRUE(fs::exists(path));
272 makeFileUnRemovable(path);
273 }
274 catch (...)
275 {
276 ADD_FAILURE() << "Should not have caught exception.";
277 }
278
279 // Temporary file should still exist
280 EXPECT_TRUE(fs::exists(path));
281
282 // Make file removable and delete it
283 makeFileRemovable(path);
284 fs::remove(path);
285 }
286}
287
288TEST_F(TemporaryFileTests, RemoveTest1)
289{
290 // Test where works
291 // Vverify temporary file exists
292 EXPECT_FALSE(tmpFile->getPath().empty());
293 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
294
295 // Save path to temporary file
296 fs::path path = tmpFile->getPath();
297
298 // Delete temporary file
299 tmpFile->remove();
300
301 // Verify path is cleared and file does not exist
302 EXPECT_TRUE(tmpFile->getPath().empty());
303 EXPECT_FALSE(fs::exists(path));
304
305 // Delete temporary file again; should do nothing
306 tmpFile->remove();
307 EXPECT_TRUE(tmpFile->getPath().empty());
308 EXPECT_FALSE(fs::exists(path));
309}
310
311TEST_F(TemporaryFileTests, RemoveTest2)
312{
313 // Test where fails
314 // Create TemporaryFile object and verify temporary file exists
315 EXPECT_FALSE(tmpFile->getPath().empty());
316 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
317
318 // Make file unremovable
319 makeFileUnRemovable(tmpFile->getPath());
320
321 try
322 {
323 // Try to delete temporary file; should fail with exception
324 tmpFile->remove();
325 ADD_FAILURE() << "Should not have reached this line.";
326 }
327 catch (const std::exception& e)
328 {
329 // This is expected. Exception message will vary.
330 }
331
332 // Make file removable again so it will be deleted by the destructor
333 makeFileRemovable(tmpFile->getPath());
334}
335
336TEST_F(TemporaryFileTests, GetPath)
337{
338 EXPECT_FALSE(tmpFile->getPath().empty());
339 EXPECT_EQ(tmpFile->getPath().parent_path(), "/tmp");
340 EXPECT_TRUE(fs::exists(tmpFile->getPath()));
341}