Move TemporaryFile class to root directory

Source code that is shared across applications is located in the root
directory of the phosphor-power repository.

The TemporaryFile class was originally created for the
phosphor-regulators application.  However it is general purpose and is
now needed by the phosphor-power-sequencer application.

Move the TemporaryFile class to the root directory.  Update C++ files
that use the TemporaryFile class since it is now in a different
namespace.  Update affected meson.build files.

Change-Id: I6d18080d2436a5da87b7ab51ac003c503caa36a3
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/meson.build b/meson.build
index badc8b5..da7a277 100644
--- a/meson.build
+++ b/meson.build
@@ -156,6 +156,7 @@
     error_hpp,
     'gpio.cpp',
     'pmbus.cpp',
+    'temporary_file.cpp',
     'utility.cpp',
     dependencies: [
         nlohmann_json_dep,
diff --git a/phosphor-regulators/src/ffdc_file.hpp b/phosphor-regulators/src/ffdc_file.hpp
index 923f09e..8ee9db8 100644
--- a/phosphor-regulators/src/ffdc_file.hpp
+++ b/phosphor-regulators/src/ffdc_file.hpp
@@ -29,6 +29,7 @@
 using FFDCFormat =
     sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
 using FileDescriptor = phosphor::power::util::FileDescriptor;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 /**
  * @class FFDCFile
diff --git a/phosphor-regulators/src/meson.build b/phosphor-regulators/src/meson.build
index c448366..e1552fe 100644
--- a/phosphor-regulators/src/meson.build
+++ b/phosphor-regulators/src/meson.build
@@ -24,7 +24,6 @@
     'rail.cpp',
     'sensor_monitoring.cpp',
     'system.cpp',
-    'temporary_file.cpp',
     'vpd.cpp',
 
     'actions/compare_presence_action.cpp',
diff --git a/phosphor-regulators/test/config_file_parser_tests.cpp b/phosphor-regulators/test/config_file_parser_tests.cpp
index f477d41..92096fb 100644
--- a/phosphor-regulators/test/config_file_parser_tests.cpp
+++ b/phosphor-regulators/test/config_file_parser_tests.cpp
@@ -69,6 +69,7 @@
 using namespace phosphor::power::regulators::config_file_parser;
 using namespace phosphor::power::regulators::config_file_parser::internal;
 using json = nlohmann::json;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 void writeConfigFile(const std::filesystem::path& pathName,
                      const std::string& contents)
diff --git a/phosphor-regulators/test/meson.build b/phosphor-regulators/test/meson.build
index 74695be..3373abb 100644
--- a/phosphor-regulators/test/meson.build
+++ b/phosphor-regulators/test/meson.build
@@ -24,7 +24,6 @@
     'sensor_monitoring_tests.cpp',
     'sensors_tests.cpp',
     'system_tests.cpp',
-    'temporary_file_tests.cpp',
     'write_verification_error_tests.cpp',
 
     'actions/action_environment_tests.cpp',
@@ -72,7 +71,8 @@
                 build_rpath: get_option('oe-sdk').allowed() ? rpath : '',
                 link_with: [
                     phosphor_regulators_library,
-                    libi2c_dev_mock
+                    libi2c_dev_mock,
+                    libpower
                 ],
                 implicit_include_directories: false,
                 include_directories: [
diff --git a/phosphor-regulators/test/validate-regulators-config_tests.cpp b/phosphor-regulators/test/validate-regulators-config_tests.cpp
index 10cd7ce..3bc52da 100644
--- a/phosphor-regulators/test/validate-regulators-config_tests.cpp
+++ b/phosphor-regulators/test/validate-regulators-config_tests.cpp
@@ -36,8 +36,8 @@
     expectJsonInvalid(configFileJson, expectedErrorMessage,                    \
                       expectedOutputMessage)
 
-using namespace phosphor::power::regulators;
 using json = nlohmann::json;
+using TemporaryFile = phosphor::power::util::TemporaryFile;
 
 const json validConfigFile = R"(
     {
diff --git a/phosphor-regulators/src/temporary_file.cpp b/temporary_file.cpp
similarity index 93%
rename from phosphor-regulators/src/temporary_file.cpp
rename to temporary_file.cpp
index 5b5954d..69be79d 100644
--- a/phosphor-regulators/src/temporary_file.cpp
+++ b/temporary_file.cpp
@@ -24,14 +24,16 @@
 #include <stdexcept>
 #include <string>
 
-namespace phosphor::power::regulators
+namespace phosphor::power::util
 {
 
+namespace fs = std::filesystem;
+
 TemporaryFile::TemporaryFile()
 {
     // Build template path required by mkstemp()
     std::string templatePath = fs::temp_directory_path() /
-                               "phosphor-regulators-XXXXXX";
+                               "phosphor-power-XXXXXX";
 
     // Generate unique file name, create file, and open it.  The XXXXXX
     // characters are replaced by mkstemp() to make the file name unique.
@@ -90,4 +92,4 @@
     }
 }
 
-} // namespace phosphor::power::regulators
+} // namespace phosphor::power::util
diff --git a/phosphor-regulators/src/temporary_file.hpp b/temporary_file.hpp
similarity index 94%
rename from phosphor-regulators/src/temporary_file.hpp
rename to temporary_file.hpp
index df97ee2..7ba4190 100644
--- a/phosphor-regulators/src/temporary_file.hpp
+++ b/temporary_file.hpp
@@ -18,11 +18,9 @@
 #include <filesystem>
 #include <utility>
 
-namespace phosphor::power::regulators
+namespace phosphor::power::util
 {
 
-namespace fs = std::filesystem;
-
 /**
  * @class TemporaryFile
  *
@@ -111,7 +109,7 @@
      *
      * @return temporary file path
      */
-    const fs::path& getPath() const
+    const std::filesystem::path& getPath() const
     {
         return path;
     }
@@ -122,7 +120,7 @@
      *
      * Empty when file has been deleted.
      */
-    fs::path path{};
+    std::filesystem::path path{};
 };
 
-} // namespace phosphor::power::regulators
+} // namespace phosphor::power::util
diff --git a/test/meson.build b/test/meson.build
index 92225b4..0b4fd20 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,27 +1,19 @@
 test(
-    'nvtest',
+    'common-code-tests',
     executable(
-        'nvtest', 'nvtest.cpp',
+        'common-code-tests',
+        'file_descriptor_tests.cpp',
+        'nvtest.cpp',
+        'temporary_file_tests.cpp',
         dependencies: [
             gmock,
             gtest,
         ],
         link_args: dynamic_linker,
         build_rpath: get_option('oe-sdk').allowed() ? rpath : '',
-        implicit_include_directories: false,
-        include_directories: '..',
-    )
-)
-
-test(
-    'file_descriptor_tests',
-    executable(
-        'file_descriptor_tests', 'file_descriptor_tests.cpp',
-        dependencies: [
-            gtest,
+        link_with: [
+            libpower
         ],
-        link_args: dynamic_linker,
-        build_rpath: get_option('oe-sdk').allowed() ? rpath : '',
         implicit_include_directories: false,
         include_directories: '..',
     )
diff --git a/phosphor-regulators/test/temporary_file_tests.cpp b/test/temporary_file_tests.cpp
similarity index 85%
rename from phosphor-regulators/test/temporary_file_tests.cpp
rename to test/temporary_file_tests.cpp
index b3bcb60..9eafa56 100644
--- a/phosphor-regulators/test/temporary_file_tests.cpp
+++ b/test/temporary_file_tests.cpp
@@ -14,18 +14,56 @@
  * limitations under the License.
  */
 #include "temporary_file.hpp"
-#include "test_utils.hpp"
 
 #include <filesystem>
+#include <fstream>
 #include <string>
 #include <utility>
 
 #include <gtest/gtest.h>
 
-using namespace phosphor::power::regulators;
-using namespace phosphor::power::regulators::test_utils;
+using namespace phosphor::power::util;
 namespace fs = std::filesystem;
 
+/**
+ * Modify the specified file so that fs::remove() fails with an exception.
+ *
+ * The file will be renamed and can be restored by calling makeFileRemovable().
+ *
+ * @param path path to the file
+ */
+inline void makeFileUnRemovable(const fs::path& path)
+{
+    // Rename the file to save its contents
+    fs::path savePath{path.native() + ".save"};
+    fs::rename(path, savePath);
+
+    // Create a directory at the original file path
+    fs::create_directory(path);
+
+    // Create a file within the directory.  fs::remove() will throw an exception
+    // if the path is a non-empty directory.
+    std::ofstream childFile{path / "childFile"};
+}
+
+/**
+ * Modify the specified file so that fs::remove() can successfully delete it.
+ *
+ * Undo the modifications from an earlier call to makeFileUnRemovable().
+ *
+ * @param path path to the file
+ */
+inline void makeFileRemovable(const fs::path& path)
+{
+    // makeFileUnRemovable() creates a directory at the file path.  Remove the
+    // directory and all of its contents.
+    fs::remove_all(path);
+
+    // Rename the file back to the original path to restore its contents
+    fs::path savePath{path.native() + ".save"};
+    fs::rename(savePath, path);
+}
+
 TEST(TemporaryFileTests, DefaultConstructor)
 {
     TemporaryFile file{};
@@ -39,7 +77,7 @@
     EXPECT_EQ(parentDir, "/tmp");
 
     std::string fileName = path.filename();
-    std::string namePrefix = "phosphor-regulators-";
+    std::string namePrefix = "phosphor-power-";
     EXPECT_EQ(fileName.compare(0, namePrefix.size(), namePrefix), 0);
 }