File System: Dependency Injection and Mock

1. Add an abstract FileSystemInterface for Dependency Injection
2. Add  FileSystemWrapper for real file system operations, which is
   called in produciton
3. Add FileSystemMock for unit test mock only
4. Add bm_mode_transition_unittest.cpp to cover file system based bm
   mode transition

Tested:
 1/14 eth                        OK              0.22s
 2/14 flash                      OK              0.21s
 3/14 machine                    OK              0.12s
 4/14 bmc_mode                   OK              0.05s
 5/14 cable                      OK              0.27s
 6/14 cpld                       OK              0.25s
 7/14 entity                     OK              0.24s
 8/14 google_accel_oob           OK              0.20s
 9/14 pcie                       OK              0.11s
10/14 poweroff                   OK              0.09s
11/14 psu                        OK              0.08s
12/14 pcie_bifurcation           OK              0.07s
13/14 bm_mode_transition         OK              0.29s
14/14 handler                    OK              0.44s

Ok:                 14
Expected Fail:      0
Fail:               0
Unexpected Pass:    0
Skipped:            0
Timeout:            0

Change-Id: I8d0d9096fbeee7af1946d7e73f548e4a249d3bee
Signed-off-by: Hao Zhou <haoooamazing@google.com>
diff --git a/handler.cpp b/handler.cpp
index 9032055..9a6ac04 100644
--- a/handler.cpp
+++ b/handler.cpp
@@ -62,26 +62,19 @@
 {
 namespace ipmi
 {
-namespace fs = std::filesystem;
 using Json = nlohmann::json;
 using namespace phosphor::logging;
 using InternalFailure =
     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 
-static constexpr auto bmDriveCleaningFlagPath = "/run/bm-drive-cleaning.flag";
-static constexpr auto bmDriveCleaningDoneFlagPath =
-    "/run/bm-drive-cleaning-done.flag";
-static constexpr auto bmDriveCleaningDoneAckFlagPath =
-    "/run/bm-drive-cleaning-done-ack.flag";
-
-uint8_t isBmcInBareMetalMode()
+uint8_t isBmcInBareMetalMode(const std::unique_ptr<FileSystemInterface>& fs)
 {
 #if BARE_METAL
     return static_cast<uint8_t>(BmcMode::BM_MODE);
 #else
     std::error_code ec;
 
-    if (fs::exists(bmDriveCleaningDoneAckFlagPath, ec))
+    if (fs->exists(bmDriveCleaningDoneAckFlagPath, ec))
     {
         std::fprintf(
             stderr,
@@ -90,9 +83,9 @@
         return static_cast<uint8_t>(BmcMode::BM_MODE);
     }
 
-    if (fs::exists(bmDriveCleaningDoneFlagPath, ec))
+    if (fs->exists(bmDriveCleaningDoneFlagPath, ec))
     {
-        fs::rename(bmDriveCleaningDoneFlagPath, bmDriveCleaningDoneAckFlagPath,
+        fs->rename(bmDriveCleaningDoneFlagPath, bmDriveCleaningDoneAckFlagPath,
                    ec);
         std::fprintf(
             stderr,
@@ -101,13 +94,11 @@
         return static_cast<uint8_t>(BmcMode::BM_MODE);
     }
 
-    if (fs::exists(BM_SIGNAL_PATH, ec))
+    if (fs->exists(BM_SIGNAL_PATH, ec))
     {
-        if (!fs::exists(bmDriveCleaningFlagPath, ec))
+        if (!fs->exists(bmDriveCleaningFlagPath, ec))
         {
-            std::ofstream ofs;
-            ofs.open(bmDriveCleaningFlagPath, std::ofstream::out);
-            ofs.close();
+            fs->create(bmDriveCleaningFlagPath);
         }
 
         std::fprintf(
@@ -127,7 +118,7 @@
 uint8_t Handler::getBmcMode()
 {
     // BM_CLEANING_MODE is not implemented yet
-    return isBmcInBareMetalMode();
+    return isBmcInBareMetalMode(this->getFs());
 }
 
 std::tuple<std::uint8_t, std::string>
@@ -157,7 +148,7 @@
     }
 
     std::error_code ec;
-    if (!fs::exists(path, ec))
+    if (!this->getFs()->exists(path, ec))
     {
         std::fprintf(stderr, "Path: '%s' doesn't exist.\n", path.c_str());
         throw IpmiException(::ipmi::ccInvalidFieldRequest);
@@ -187,7 +178,7 @@
     // Check for file
 
     std::error_code ec;
-    if (!fs::exists(opath.str(), ec))
+    if (!this->getFs()->exists(opath.str(), ec))
     {
         std::fprintf(stderr, "Path: '%s' doesn't exist.\n",
                      opath.str().c_str());
@@ -480,6 +471,11 @@
     return sdbusplus::bus::new_default();
 }
 
+const std::unique_ptr<FileSystemInterface>& Handler::getFs() const
+{
+    return this->fsPtr;
+}
+
 uint32_t Handler::accelOobDeviceCount() const
 {
     ArrayOfObjectPathsAndTieredAnyTypeLists data;
@@ -674,7 +670,8 @@
 
 void Handler::linuxBootDone() const
 {
-    if (isBmcInBareMetalMode() != static_cast<uint8_t>(BmcMode::BM_MODE))
+    if (isBmcInBareMetalMode(this->fsPtr) !=
+        static_cast<uint8_t>(BmcMode::BM_MODE))
     {
         return;
     }