tools: implement bt sendcontents

Implement the block transfer (really not blocktransfer only)
sendcontents handler.  This handler sends the file contents within
the IPMI packets themselves.

Note: This is really used for kcs, etc, but it's called bt to avoid
confusion with general ipmi code.

Change-Id: I310034a6afdf0eb25894e658ccee42e6394aa4d2
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index 3d51fa4..0b01997 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -28,6 +28,7 @@
 	firmware_commit_unittest \
 	file_handler_unittest \
 	tools_blob_unittest \
+	tools_bt_unittest \
 	tools_updater_unittest \
 	tools_ipmi_unittest
 
@@ -72,6 +73,9 @@
 tools_blob_unittest_SOURCES = tools_blob_unittest.cpp
 tools_blob_unittest_LDADD = $(top_builddir)/tools/blob_handler.o
 
+tools_bt_unittest_SOURCES = tools_bt_unittest.cpp
+tools_bt_unittest_LDADD = $(top_builddir)/tools/bt.o
+
 tools_updater_unittest_SOURCES = tools_updater_unittest.cpp
 tools_updater_unittest_LDADD = $(top_builddir)/tools/updater.o
 
diff --git a/test/tools_bt_unittest.cpp b/test/tools_bt_unittest.cpp
new file mode 100644
index 0000000..24511c3
--- /dev/null
+++ b/test/tools_bt_unittest.cpp
@@ -0,0 +1,48 @@
+#include "blob_interface_mock.hpp"
+#include "bt.hpp"
+#include "internal_sys_mock.hpp"
+
+#include <cstring>
+
+#include <gtest/gtest.h>
+
+namespace host_tool
+{
+
+using ::testing::_;
+using ::testing::ContainerEq;
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::NotNull;
+using ::testing::Return;
+
+TEST(BtHandlerTest, verifySendsFileContents)
+{
+    /* In this very basic test, we'll feed the bt handler data from the internal
+     * syscall mock and catch the writes via the blob mock.
+     */
+    internal::InternalSysMock sysMock;
+    BlobInterfaceMock blobMock;
+
+    BtDataHandler handler(&blobMock, &sysMock);
+    std::string filePath = "/asdf";
+    int fd = 1;
+    std::uint16_t session = 0xbeef;
+    std::vector<std::uint8_t> bytes = {'1', '2', '3', '4'};
+
+    EXPECT_CALL(sysMock, open(Eq(filePath), _)).WillOnce(Return(fd));
+    EXPECT_CALL(sysMock, read(fd, NotNull(), _))
+        .WillOnce(Invoke([&](int fd, void* buf, std::size_t count) {
+            EXPECT_TRUE(count > bytes.size());
+            std::memcpy(buf, bytes.data(), bytes.size());
+            return bytes.size();
+        }))
+        .WillOnce(Return(0));
+    EXPECT_CALL(sysMock, close(fd)).WillOnce(Return(0));
+
+    EXPECT_CALL(blobMock, writeBytes(session, 0, ContainerEq(bytes)));
+
+    EXPECT_TRUE(handler.sendContents(filePath, session));
+}
+
+} // namespace host_tool