bios_setting: Add a write handler

Tested:
```
// Test that it writes a new file if it doesn't exist
~# rm /run/oem_bios_setting

// Invalid command (no size / payload)
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x19
Unable to send RAW command (channel=0x0 netfn=0x2e lun=0x0 cmd=0x32 rsp=0xc7): Request data length invalid

// Invalid command (size doesn't match)
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x19 0x01 0x30 0x31
Unable to send RAW command (channel=0x0 netfn=0x2e lun=0x0 cmd=0x32 rsp=0xc7): Request data length invalid

// Command success
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x19 0x02 0x30 0x31
 79 2b 00 19 02

// Read back
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x18
 79 2b 00 18 02 30 31
~# cat /run/oem_bios_setting
01~#

// Verify overwrite works (truncates the previous bytes)
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x19 0x01 0x33
 79 2b 00 19 01
~# cat /run/oem_bios_setting
3~#
~# ipmitool raw 0x2e 0x32 0x79 0x2b 0x00 0x18
 79 2b 00 18 01 33
```

Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: I84db782da9b2f121c0a81a855692b5ca25ffda54
diff --git a/test/bios_setting_unittest.cpp b/test/bios_setting_unittest.cpp
index 45373f4..1d7feb8 100644
--- a/test/bios_setting_unittest.cpp
+++ b/test/bios_setting_unittest.cpp
@@ -84,5 +84,77 @@
     std::remove(filename.c_str());
 }
 
+TEST_F(BiosSettingTest, InvalidRequestWrite)
+{
+    // Empty request
+    std::vector<uint8_t> request = {};
+
+    HandlerMock hMock;
+    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
+              writeBiosSetting(request, &hMock));
+
+    // Request with payload size 1 but no payload
+    request = {0x01};
+    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
+              writeBiosSetting(request, &hMock));
+
+    // Request with payload size 1 but actual payload size of 2 bytes
+    request = {0x01, 0x02, 0x03};
+    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
+              writeBiosSetting(request, &hMock));
+
+    // Request with payload size 2 but actual payload of 1 byte
+    request = {0x02, 0x02};
+    EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
+              writeBiosSetting(request, &hMock));
+}
+
+TEST_F(BiosSettingTest, SuccessfulWrite)
+{
+    std::vector<uint8_t> request = {0x02, 0xDE, 0xAD};
+
+    // Write a dummy file to get around permission issues with CI
+    // (Not needed in local CI)
+    writeTmpFile({});
+    HandlerMock hMock;
+    auto reply = writeBiosSetting(request, &hMock, filename);
+    auto result = ValidateReply(reply);
+    auto& data = result.second;
+
+    EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
+    EXPECT_EQ(std::vector<uint8_t>{2}, data);
+
+    // Validate the payload is correct
+    reply = readBiosSetting(request, &hMock, filename);
+    result = ValidateReply(reply);
+    data = result.second;
+
+    EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
+    EXPECT_EQ(request.size() - 1, data.front());
+    EXPECT_EQ(request, data);
+
+    // Verify that we can write a shorter string and it'll replace the original
+    // content of the file
+    request = {0x01, 0x0A};
+
+    reply = writeBiosSetting(request, &hMock, filename);
+    result = ValidateReply(reply);
+    data = result.second;
+
+    EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
+    EXPECT_EQ(std::vector<uint8_t>{1}, data);
+
+    // Validate the payload is correct
+    reply = readBiosSetting(request, &hMock, filename);
+    result = ValidateReply(reply);
+    data = result.second;
+
+    EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
+    EXPECT_EQ(request.size() - 1, data.front());
+    EXPECT_EQ(request, data);
+    // Cleanup the settings file
+    std::remove(filename.c_str());
+}
+
 } // namespace ipmi
 } // namespace google