Add pattern write and verify to erase

The goals are to write a non-compressible and verifiable pattern to the
drive as a means to validate that the drive is working, and ensure all
blocks have been overwritten.

Tested:
$ systemctl stop emmc.service
$ ./eStoraged  -b /dev/mmcblk0&
$busctl call xyz.openbmc_project.eStoraged.mmcblk0 /xyz/openbmc_project/storage/mmcblk0 xyz.openbmc_project.Inventory.Item.Volume Erase s xyz.openbmc_project.Inventory.Item.Volume.EraseMethod.LogicalOverWrite --timeout=1200

$busctl call xyz.openbmc_project.eStoraged.mmcblk0 /xyz/openbmc_project/storage/mmcblk0 xyz.openbmc_project.Inventory.Item.Volume Erase s xyz.openbmc_project.Inventory.Item.Volume.EraseMethod.LogicalVerify --timeout=1200

$echo "jebr" > /dev/mmcblk0

$busctl call xyz.openbmc_project.eStoraged.mmcblk0 /xyz/openbmc_project/storage/mmcblk0 xyz.openbmc_project.Inventory.Item.Volume Erase s xyz.openbmc_project.Inventory.Item.Volume.EraseMethod.LogicalVerify --timeout=1200
Call failed: The operation failed internally.

Change-Id: Ibc1254279b1f46246eb37056ea6e4e1a57159bb9
Signed-off-by: John Edward Broadbent <jebr@google.com>
diff --git a/src/test/erase/pattern_test.cpp b/src/test/erase/pattern_test.cpp
new file mode 100644
index 0000000..55e83a5
--- /dev/null
+++ b/src/test/erase/pattern_test.cpp
@@ -0,0 +1,81 @@
+#include "estoraged_conf.hpp"
+#include "pattern.hpp"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdplus/fd/create.hpp>
+#include <stdplus/fd/managed.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+#include <system_error>
+
+#include <gmock/gmock-matchers.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+using stdplus::fd::ManagedFd;
+
+class MockManagedFd : public ManagedFd
+{
+  public:
+    MockManagedFd(int fd) : ManagedFd(std::move(fd))
+    {}
+    ~MockManagedFd()
+    {}
+};
+
+TEST(pattern, patternPass)
+{
+    uint64_t size = 4096;
+    int fds[2];
+    Pattern pass("fileName");
+    if (pipe(fds))
+    {
+        FAIL();
+    }
+    MockManagedFd writeFd(fds[1]);
+    EXPECT_NO_THROW(pass.writePattern(size, writeFd));
+    MockManagedFd verifyFd(fds[0]);
+    EXPECT_NO_THROW(pass.verifyPattern(size, verifyFd));
+}
+
+/* This test that pattern writes the correct number of bytes even if
+ * size of the drive is not divisable by the block size
+ */
+TEST(pattern, patternPassNotDivisible)
+{
+    uint64_t size = 4097;
+    // 4097 is not divisible by the block size, and we expect no errors
+    int fds[2];
+    Pattern pass("fileName");
+    if (pipe(fds))
+    {
+        FAIL();
+    }
+    MockManagedFd writeFd(fds[1]);
+    EXPECT_NO_THROW(pass.writePattern(size, writeFd));
+    MockManagedFd verifyFd(fds[0]);
+    EXPECT_NO_THROW(pass.verifyPattern(size, verifyFd));
+}
+
+TEST(pattern, patternsDontMatch)
+{
+    uint64_t size = 4096;
+    int fds[2];
+    Pattern pass("fileName");
+    if (pipe(fds))
+    {
+        FAIL();
+    }
+    int dummyValue = 88;
+    if (::write(fds[1], &dummyValue, sizeof(dummyValue)) != sizeof(dummyValue))
+    {
+        FAIL();
+    }
+    MockManagedFd writeFd(fds[1]);
+    pass.writePattern(size - sizeof(dummyValue), writeFd);
+    MockManagedFd verifyFd(fds[0]);
+    EXPECT_THROW(pass.verifyPattern(size, verifyFd), InternalFailure);
+}
diff --git a/src/test/meson.build b/src/test/meson.build
index 8f05182..0373840 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -3,6 +3,7 @@
 
 tests = [
   'erase/verifyGeometry_test',
+  'erase/pattern_test',
   'estoraged_test',
 ]