flash-ipmi: implement flashAbort

Change-Id: I7674790a12772ecfd15826d861fca6a56e31bb6f
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/flash-ipmi.cpp b/flash-ipmi.cpp
index 6c75835..a9603dd 100644
--- a/flash-ipmi.cpp
+++ b/flash-ipmi.cpp
@@ -58,6 +58,20 @@
     closeFile(&hashFd);
 }
 
+void FlashUpdate::deleteEverything()
+{
+    /* Assumes you've called closeEverything() already */
+
+    (void)std::remove(tmpPath.c_str());
+    (void)std::remove(verifyPath.c_str());
+
+    /* hashPath is optional. */
+    if (!hashPath.empty())
+    {
+        (void)std::remove(hashPath.c_str());
+    }
+}
+
 FlashUpdate::~FlashUpdate()
 {
     /* Close without deleting.  This object can only be destroyed if the ipmi
@@ -71,7 +85,14 @@
 {
     closeEverything();
 
-    /* TODO: And now delete everything */
+    /* Stop the systemd unit if it was running. */
+    auto method = bus.new_method_call(systemdService, systemdRoot,
+                                      systemdInterface, "StopUnit");
+    method.append(verifyTarget);
+    method.append("replace");
+    bus.call_noreply(method);
+
+    deleteEverything();
     return;
 }
 
@@ -195,9 +216,6 @@
 
 bool FlashUpdate::startDataVerification()
 {
-    /* TODO: Look for injection point to test this. */
-    auto bus = sdbusplus::bus::new_default();
-
     auto method = bus.new_method_call(systemdService, systemdRoot,
                                       systemdInterface, "StartUnit");
     method.append(verifyTarget);
@@ -209,8 +227,8 @@
 
 bool FlashUpdate::abortUpdate()
 {
-    /* TODO: implement. */
-    return false;
+    abortEverything();
+    return true;
 }
 
 VerifyCheckResponse FlashUpdate::checkVerify()
diff --git a/flash-ipmi.hpp b/flash-ipmi.hpp
index 4a13edb..908963c 100644
--- a/flash-ipmi.hpp
+++ b/flash-ipmi.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <cstdio>
+#include <sdbusplus/bus.hpp>
 #include <string>
 #include <vector>
 
@@ -169,15 +170,15 @@
 class FlashUpdate : public UpdateInterface
 {
   public:
-    FlashUpdate(const std::string& stagingPath, const std::string& verifyPath,
-                const std::string& hash = "") :
-        flashLength(0),
-        flashFd(nullptr), tmpPath(stagingPath), hashLength(0), hashFd(nullptr),
-        hashPath(hash), verifyPath(verifyPath){};
+    FlashUpdate(sdbusplus::bus::bus&& bus, const std::string& stagingPath,
+                const std::string& verifyPath, const std::string& hash = "") :
+        bus(std::move(bus)),
+        flashLength(0), flashFd(nullptr), tmpPath(stagingPath), hashLength(0),
+        hashFd(nullptr), hashPath(hash), verifyPath(verifyPath){};
     ~FlashUpdate();
 
-    FlashUpdate(const FlashUpdate&) = default;
-    FlashUpdate& operator=(const FlashUpdate&) = default;
+    FlashUpdate(const FlashUpdate&) = delete;
+    FlashUpdate& operator=(const FlashUpdate&) = delete;
     FlashUpdate(FlashUpdate&&) = default;
     FlashUpdate& operator=(FlashUpdate&&) = default;
 
@@ -206,6 +207,11 @@
                     const std::vector<uint8_t>& bytes);
 
     /**
+     * Tries to delete everything.
+     */
+    void deleteEverything();
+
+    /**
      * Tries to close out everything.
      */
     void closeEverything();
@@ -222,6 +228,9 @@
      */
     bool openEverything();
 
+    /* A bus. */
+    sdbusplus::bus::bus bus;
+
     /* The length of the flash image in bytes. */
     uint32_t flashLength;
 
diff --git a/main.cpp b/main.cpp
index 5385348..961a131 100644
--- a/main.cpp
+++ b/main.cpp
@@ -86,8 +86,8 @@
 
 void setupGlobalOemFlashControl()
 {
-    flashUpdateSingleton =
-        std::make_unique<FlashUpdate>(stagingPath, statusPath, hashPath);
+    flashUpdateSingleton = std::make_unique<FlashUpdate>(
+        sdbusplus::bus::new_default(), stagingPath, statusPath, hashPath);
 
 #ifdef ENABLE_GOOGLE
     oem::Router* router = oem::mutableRouter();
diff --git a/test/Makefile.am b/test/Makefile.am
index 6666d68..c6f2bc2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -27,7 +27,8 @@
 	flash_hashstart_unittest \
 	flash_hashdata_unittest \
 	flash_hashfinish_unittest \
-	flash_checkverify_unittest
+	flash_checkverify_unittest \
+	flash_flashabort_unittest
 
 TESTS = $(check_PROGRAMS)
 
@@ -84,3 +85,6 @@
 
 flash_checkverify_unittest_SOURCES = flash_checkverify_unittest.cpp
 flash_checkverify_unittest_LDADD = $(top_builddir)/flash-ipmi.o $(SDBUSPLUS_LIBS)
+
+flash_flashabort_unittest_SOURCES = flash_flashabort_unittest.cpp
+flash_flashabort_unittest_LDADD = $(top_builddir)/flash-ipmi.o $(SDBUSPLUS_LIBS)
diff --git a/test/flash_checkverify_unittest.cpp b/test/flash_checkverify_unittest.cpp
index c64de82..0f2a513 100644
--- a/test/flash_checkverify_unittest.cpp
+++ b/test/flash_checkverify_unittest.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <fstream>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 #include <vector>
 
@@ -43,7 +44,10 @@
 
     std::string vname = std::tmpnam(nullptr);
 
-    FlashUpdate updater(name, vname);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, vname);
 
     for (const auto& test : tests)
     {
diff --git a/test/flash_flashabort_unittest.cpp b/test/flash_flashabort_unittest.cpp
new file mode 100644
index 0000000..64039ed
--- /dev/null
+++ b/test/flash_flashabort_unittest.cpp
@@ -0,0 +1,76 @@
+#include "flash-ipmi.hpp"
+
+#include <cstdio>
+#include <cstring>
+#include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
+#include <string>
+
+#define THIRTYTWO_MIB 33554432
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::StrEq;
+
+TEST(FlashIpmiAbortTest, VerifyItDeletesAndStopsServiced)
+{
+    // Verify that once everything is started, the image and hash are deleted
+    // and it will try to stop the verification service.
+
+    std::string iname = std::tmpnam(nullptr);
+    std::string vname = std::tmpnam(nullptr);
+    std::string hname = std::tmpnam(nullptr);
+
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), iname, vname, hname);
+
+    std::vector<uint8_t> ibytes = {0xaa, 0x55};
+    std::vector<uint8_t> hbytes = {0xcc, 0x65};
+
+    // Send the bytes up for the image.
+    EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
+    EXPECT_TRUE(updater.flashData(0, ibytes));
+    EXPECT_TRUE(updater.flashFinish());
+
+    // Send the bytes up for the hash.
+    EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
+    EXPECT_TRUE(updater.hashData(0, hbytes));
+    EXPECT_TRUE(updater.hashFinish());
+
+    // Verify the image bytes.
+    auto file = std::fopen(iname.c_str(), "r");
+    EXPECT_TRUE(file);
+    uint8_t buffer[2];
+    auto read = std::fread(buffer, 1, ibytes.size(), file);
+    EXPECT_EQ(read, ibytes.size());
+    EXPECT_EQ(0, std::memcmp(buffer, ibytes.data(), ibytes.size()));
+    std::fclose(file);
+
+    // Verify the hash bytes.
+    file = std::fopen(hname.c_str(), "r");
+    EXPECT_TRUE(file);
+    read = std::fread(buffer, 1, hbytes.size(), file);
+    EXPECT_EQ(read, hbytes.size());
+    EXPECT_EQ(0, std::memcmp(buffer, hbytes.data(), hbytes.size()));
+    std::fclose(file);
+
+    EXPECT_CALL(sdbus_mock,
+                sd_bus_message_new_method_call(
+                    IsNull(), NotNull(), StrEq("org.freedesktop.systemd1"),
+                    StrEq("/org/freedesktop/systemd1"),
+                    StrEq("org.freedesktop.systemd1.Manager"),
+                    StrEq("StopUnit")))
+        .WillOnce(Return(0));
+
+    // Send the abort.
+    EXPECT_TRUE(updater.abortUpdate());
+
+    // Verify the files are gone.
+    file = std::fopen(iname.c_str(), "r");
+    EXPECT_FALSE(file);
+    file = std::fopen(hname.c_str(), "r");
+    EXPECT_FALSE(file);
+}
diff --git a/test/flash_flashdata_unittest.cpp b/test/flash_flashdata_unittest.cpp
index 112565a..17aeeb6 100644
--- a/test/flash_flashdata_unittest.cpp
+++ b/test/flash_flashdata_unittest.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <cstring>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 #include <vector>
 
@@ -30,7 +31,10 @@
     // Verify that there is sanity checking.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     EXPECT_FALSE(updater.flashData(0, bytes));
 
     // Verify the file doesn't exist.
@@ -43,7 +47,10 @@
     // Verify that under normal usage it writes the bytes.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     updater.start(THIRTYTWO_MIB);
     EXPECT_TRUE(updater.flashData(0, bytes));
 
@@ -65,7 +72,10 @@
 
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     updater.start(THIRTYTWO_MIB);
     EXPECT_TRUE(updater.flashData(2, bytes));
 
diff --git a/test/flash_flashfinish_unittest.cpp b/test/flash_flashfinish_unittest.cpp
index e160b29..84a9e40 100644
--- a/test/flash_flashfinish_unittest.cpp
+++ b/test/flash_flashfinish_unittest.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <cstring>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 #include <vector>
 
@@ -30,7 +31,10 @@
     // Verify that there is sanity checking
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     EXPECT_FALSE(updater.flashFinish());
 
     // Verify the file doesn't exist.
@@ -43,7 +47,10 @@
     // Verify that under normal usage it closes the file.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     updater.start(THIRTYTWO_MIB);
     EXPECT_TRUE(updater.flashFinish());
 
@@ -59,7 +66,10 @@
     // be closed twice.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "");
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "");
     updater.start(THIRTYTWO_MIB);
     EXPECT_TRUE(updater.flashFinish());
 
diff --git a/test/flash_hashdata_unittest.cpp b/test/flash_hashdata_unittest.cpp
index 8d7be77..0a011e5 100644
--- a/test/flash_hashdata_unittest.cpp
+++ b/test/flash_hashdata_unittest.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <cstring>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 #include <vector>
 
@@ -35,7 +36,10 @@
 
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_FALSE(updater.hashData(0, bytes));
 }
 
@@ -44,7 +48,10 @@
     // Verify the normal use case works.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.hashData(0, bytes));
@@ -67,7 +74,10 @@
 
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.hashData(2, bytes));
diff --git a/test/flash_hashfinish_unittest.cpp b/test/flash_hashfinish_unittest.cpp
index 12ff7a8..2d5e5b0 100644
--- a/test/flash_hashfinish_unittest.cpp
+++ b/test/flash_hashfinish_unittest.cpp
@@ -3,6 +3,7 @@
 #include <cstdio>
 #include <cstring>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 #include <vector>
 
@@ -33,7 +34,10 @@
     // Verify that there is sanity checking
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_FALSE(updater.hashFinish());
 
     // Verify the file doesn't exist.
@@ -46,7 +50,10 @@
     // Verify that under normal usage it closes the file.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.hashFinish());
@@ -63,7 +70,10 @@
     // be closed twice.
     std::vector<uint8_t> bytes = {0xaa, 0x55};
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.hashFinish());
diff --git a/test/flash_hashstart_unittest.cpp b/test/flash_hashstart_unittest.cpp
index 60f8df1..3cf46ed 100644
--- a/test/flash_hashstart_unittest.cpp
+++ b/test/flash_hashstart_unittest.cpp
@@ -2,6 +2,7 @@
 
 #include <cstdio>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 
 #define THIRTYTWO_MIB 33554432
@@ -13,7 +14,10 @@
     std::string name = std::tmpnam(nullptr);
     std::string name2 = std::tmpnam(nullptr);
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_FALSE(updater.startHash(THIRTYTWO_MIB));
 
     (void)std::remove(name.c_str());
@@ -27,7 +31,10 @@
     std::string name = std::tmpnam(nullptr);
     std::string name2 = std::tmpnam(nullptr);
 
-    FlashUpdate updater(name, "", name2);
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
+    FlashUpdate updater(std::move(bus_mock), name, "", name2);
     EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
     EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
 
diff --git a/test/flash_start_unittest.cpp b/test/flash_start_unittest.cpp
index 81c2d45..a70359a 100644
--- a/test/flash_start_unittest.cpp
+++ b/test/flash_start_unittest.cpp
@@ -2,6 +2,7 @@
 
 #include <cstdio>
 #include <gtest/gtest.h>
+#include <sdbusplus/test/sdbus_mock.hpp>
 #include <string>
 
 #define THIRTYTWO_MIB 33554432
@@ -11,9 +12,12 @@
     // The interface does not currently support failure injection, so let's
     // simply verify it does what we think it should.
 
+    sdbusplus::SdBusMock sdbus_mock;
+    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+
     std::string name = std::tmpnam(nullptr);
 
-    FlashUpdate updater(name, "");
+    FlashUpdate updater(std::move(bus_mock), name, "");
     updater.start(THIRTYTWO_MIB);
 
     auto file = std::fopen(name.c_str(), "r");