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 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 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 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 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 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 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