Create TemporarySubDirectory class
Create class that automatically creates and deletes a temporary
subdirectory.
The subdirectory will be located beneath the system temporary directory
(such as /tmp).
Change-Id: Id14d33b47658f144ad17c6741ec36f58492a88e2
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/test/temporary_subdirectory_tests.cpp b/test/temporary_subdirectory_tests.cpp
new file mode 100644
index 0000000..0b0188f
--- /dev/null
+++ b/test/temporary_subdirectory_tests.cpp
@@ -0,0 +1,284 @@
+/**
+ * Copyright © 2024 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "temporary_subdirectory.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <string>
+#include <utility>
+
+#include <gtest/gtest.h>
+
+using namespace phosphor::power::util;
+namespace fs = std::filesystem;
+
+TEST(TemporarySubDirectoryTests, DefaultConstructor)
+{
+ TemporarySubDirectory subdirectory{};
+
+ fs::path path = subdirectory.getPath();
+ EXPECT_FALSE(path.empty());
+ EXPECT_TRUE(fs::exists(path));
+ EXPECT_TRUE(fs::is_directory(path));
+
+ fs::path parentDir = path.parent_path();
+ EXPECT_EQ(parentDir, "/tmp");
+
+ std::string baseName = path.filename();
+ EXPECT_TRUE(baseName.starts_with("phosphor-power-"));
+}
+
+TEST(TemporarySubDirectoryTests, MoveConstructor)
+{
+ // Create first object and verify subdirectory exists
+ TemporarySubDirectory subdirectory1{};
+ EXPECT_FALSE(subdirectory1.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
+
+ // Save path to subdirectory
+ fs::path path = subdirectory1.getPath();
+
+ // Create second object by moving first object
+ TemporarySubDirectory subdirectory2{std::move(subdirectory1)};
+
+ // Verify first object now has an empty path
+ EXPECT_TRUE(subdirectory1.getPath().empty());
+
+ // Verify second object now owns same subdirectory and subdirectory exists
+ EXPECT_EQ(subdirectory2.getPath(), path);
+ EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
+}
+
+TEST(TemporarySubDirectoryTests, MoveAssignmentOperator)
+{
+ // Test where works: object is moved
+ {
+ // Create first object and verify subdirectory exists
+ TemporarySubDirectory subdirectory1{};
+ EXPECT_FALSE(subdirectory1.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
+
+ // Save path to first subdirectory
+ fs::path path1 = subdirectory1.getPath();
+
+ // Create second object and verify subdirectory exists
+ TemporarySubDirectory subdirectory2{};
+ EXPECT_FALSE(subdirectory2.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
+
+ // Save path to second subdirectory
+ fs::path path2 = subdirectory2.getPath();
+
+ // Verify temporary subdirectories are different
+ EXPECT_NE(path1, path2);
+
+ // Move first object into the second
+ subdirectory2 = std::move(subdirectory1);
+
+ // Verify first object now has an empty path
+ EXPECT_TRUE(subdirectory1.getPath().empty());
+
+ // Verify second object now owns first subdirectory and subdirectory
+ // exists
+ EXPECT_EQ(subdirectory2.getPath(), path1);
+ EXPECT_TRUE(fs::exists(path1));
+
+ // Verify second subdirectory was deleted
+ EXPECT_FALSE(fs::exists(path2));
+ }
+
+ // Test where does nothing: object moved into itself
+ {
+ // Create object and verify subdirectory exists
+ TemporarySubDirectory subdirectory{};
+ EXPECT_FALSE(subdirectory.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory.getPath()));
+
+ // Save path to subdirectory
+ fs::path path = subdirectory.getPath();
+
+ // Try to move object into itself; should do nothing
+ subdirectory = static_cast<TemporarySubDirectory&&>(subdirectory);
+
+ // Verify object still owns same subdirectory and subdirectory exists
+ EXPECT_EQ(subdirectory.getPath(), path);
+ EXPECT_TRUE(fs::exists(path));
+ }
+
+ // Test where fails: Cannot delete subdirectory
+ {
+ // Create first object and verify subdirectory exists
+ TemporarySubDirectory subdirectory1{};
+ EXPECT_FALSE(subdirectory1.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory1.getPath()));
+
+ // Save path to first subdirectory
+ fs::path path1 = subdirectory1.getPath();
+
+ // Create second object and verify subdirectory exists
+ TemporarySubDirectory subdirectory2{};
+ EXPECT_FALSE(subdirectory2.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory2.getPath()));
+
+ // Save path to second subdirectory
+ fs::path path2 = subdirectory2.getPath();
+
+ // Verify temporary subdirectories are different
+ EXPECT_NE(path1, path2);
+
+ // Change second subdirectory to unreadable so it cannot be removed
+ fs::permissions(path2, fs::perms::none);
+
+ try
+ {
+ // Try to move first object into the second; should throw exception
+ subdirectory2 = std::move(subdirectory1);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::exception& e)
+ {
+ // This is expected. Exception message will vary.
+ }
+
+ // Change second subdirectory to readable/writable so it can be removed
+ fs::permissions(path2, fs::perms::owner_all);
+
+ // Verify first object has not changed and first subdirectory exists
+ EXPECT_EQ(subdirectory1.getPath(), path1);
+ EXPECT_TRUE(fs::exists(path1));
+
+ // Verify second object has not changed and second subdirectory exists
+ EXPECT_EQ(subdirectory2.getPath(), path2);
+ EXPECT_TRUE(fs::exists(path2));
+ }
+}
+
+TEST(TemporarySubDirectoryTests, Destructor)
+{
+ // Test where works: Subdirectory is deleted
+ {
+ fs::path path{};
+ {
+ TemporarySubDirectory subdirectory{};
+ path = subdirectory.getPath();
+ EXPECT_TRUE(fs::exists(path));
+ }
+ EXPECT_FALSE(fs::exists(path));
+ }
+
+ // Test where works: Subdirectory was already deleted
+ {
+ fs::path path{};
+ {
+ TemporarySubDirectory subdirectory{};
+ path = subdirectory.getPath();
+ EXPECT_TRUE(fs::exists(path));
+ subdirectory.remove();
+ EXPECT_FALSE(fs::exists(path));
+ }
+ EXPECT_FALSE(fs::exists(path));
+ }
+
+ // Test where fails: Cannot delete subdirectory: No exception thrown
+ {
+ fs::path path{};
+ try
+ {
+ TemporarySubDirectory subdirectory{};
+ path = subdirectory.getPath();
+ EXPECT_TRUE(fs::exists(path));
+
+ // Change subdirectory to unreadable so it cannot be removed
+ fs::permissions(path, fs::perms::none);
+ }
+ catch (...)
+ {
+ ADD_FAILURE() << "Should not have caught exception.";
+ }
+
+ // Change subdirectory to readable/writable so it can be removed
+ fs::permissions(path, fs::perms::owner_all);
+
+ // Subdirectory should still exist
+ EXPECT_TRUE(fs::exists(path));
+
+ // Delete subdirectory
+ fs::remove_all(path);
+ }
+}
+
+TEST(TemporarySubDirectoryTests, Remove)
+{
+ // Test where works
+ {
+ // Create object and verify subdirectory exists
+ TemporarySubDirectory subdirectory{};
+ EXPECT_FALSE(subdirectory.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory.getPath()));
+
+ // Save path to subdirectory
+ fs::path path = subdirectory.getPath();
+
+ // Delete subdirectory
+ subdirectory.remove();
+
+ // Verify path is cleared and subdirectory does not exist
+ EXPECT_TRUE(subdirectory.getPath().empty());
+ EXPECT_FALSE(fs::exists(path));
+
+ // Delete subdirectory again; should do nothing
+ subdirectory.remove();
+ EXPECT_TRUE(subdirectory.getPath().empty());
+ EXPECT_FALSE(fs::exists(path));
+ }
+
+ // Test where fails
+ {
+ // Create object and verify subdirectory exists
+ TemporarySubDirectory subdirectory{};
+ EXPECT_FALSE(subdirectory.getPath().empty());
+ EXPECT_TRUE(fs::exists(subdirectory.getPath()));
+
+ // Save path to subdirectory
+ fs::path path = subdirectory.getPath();
+
+ // Change subdirectory to unreadable so it cannot be removed
+ fs::permissions(path, fs::perms::none);
+
+ try
+ {
+ // Try to delete subdirectory; should fail with exception
+ subdirectory.remove();
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::exception& e)
+ {
+ // This is expected. Exception message will vary.
+ }
+
+ // Change subdirectory to readable/writable so it can be deleted by
+ // destructor
+ fs::permissions(path, fs::perms::owner_all);
+ }
+}
+
+TEST(TemporarySubDirectoryTests, GetPath)
+{
+ TemporarySubDirectory subdirectory{};
+ EXPECT_FALSE(subdirectory.getPath().empty());
+ EXPECT_EQ(subdirectory.getPath().parent_path(), "/tmp");
+ EXPECT_TRUE(fs::exists(subdirectory.getPath()));
+}