Add IPMI interface for CustomAccel service
Change-Id: I28a8976e382b457233ac521e9ab71f75abe029d1
Signed-off-by: Steve Foreman <foremans@google.com>
diff --git a/test/google_accel_oob_unittest.cpp b/test/google_accel_oob_unittest.cpp
new file mode 100644
index 0000000..163b602
--- /dev/null
+++ b/test/google_accel_oob_unittest.cpp
@@ -0,0 +1,239 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "commands.hpp"
+#include "errors.hpp"
+#include "google_accel_oob.hpp"
+#include "handler_mock.hpp"
+
+#include <ipmid/api.h>
+
+#include <gtest/gtest.h>
+
+namespace google
+{
+namespace ipmi
+{
+
+using ::testing::Return;
+
+TEST(GoogleAccelOobTest, DeviceCount_Success)
+{
+ ::testing::StrictMock<HandlerMock> h;
+
+ uint8_t reqBuf[1]; // Could be 0, but zero-length arrays are an extension
+
+ struct Reply
+ {
+ uint32_t count;
+ } __attribute__((packed));
+
+ constexpr uint32_t kTestDeviceCount = 2;
+
+ EXPECT_CALL(h, accelOobDeviceCount()).WillOnce(Return(kTestDeviceCount));
+
+ Resp r = accelOobDeviceCount(reqBuf, &h);
+
+ const auto response = std::get<0>(r);
+ EXPECT_EQ(response, IPMI_CC_OK);
+
+ const auto payload = std::get<1>(r);
+ ASSERT_EQ(payload.has_value(), true);
+ const auto payload_tuple = payload.value();
+ const auto reply_cmd = std::get<0>(payload_tuple);
+ EXPECT_EQ(reply_cmd, SysAccelOobDeviceCount);
+ const auto reply_buff = std::get<1>(payload_tuple);
+ ASSERT_EQ(reply_buff.size(), sizeof(Reply));
+
+ auto* reply = reinterpret_cast<const Reply*>(reply_buff.data());
+ EXPECT_EQ(reply->count, kTestDeviceCount);
+}
+
+TEST(GoogleAccelOobTest, DeviceName_Success)
+{
+ ::testing::StrictMock<HandlerMock> h;
+
+ struct Request
+ {
+ uint32_t index;
+ } __attribute__((packed));
+
+ struct Reply
+ {
+ uint32_t index;
+ uint8_t length;
+ char name[1];
+ } __attribute__((packed));
+
+ constexpr uint32_t kTestDeviceIndex = 0;
+ const std::string kTestDeviceName("testDeviceName");
+
+ EXPECT_CALL(h, accelOobDeviceName(kTestDeviceIndex))
+ .WillOnce(Return(kTestDeviceName));
+
+ Request reqBuf{kTestDeviceIndex};
+ Resp r = accelOobDeviceName(
+ std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)),
+ &h);
+
+ const auto response = std::get<0>(r);
+ EXPECT_EQ(response, IPMI_CC_OK);
+
+ const auto payload = std::get<1>(r);
+ ASSERT_EQ(payload.has_value(), true);
+ const auto payload_tuple = payload.value();
+ const auto reply_cmd = std::get<0>(payload_tuple);
+ EXPECT_EQ(reply_cmd, SysAccelOobDeviceName);
+ const auto reply_buff = std::get<1>(payload_tuple);
+ ASSERT_GE(reply_buff.size(), sizeof(Reply));
+
+ auto* reply = reinterpret_cast<const Reply*>(reply_buff.data());
+ EXPECT_EQ(reply->index, kTestDeviceIndex);
+ EXPECT_EQ(reply->length, kTestDeviceName.length());
+ EXPECT_STREQ(reply->name, kTestDeviceName.c_str());
+}
+
+TEST(GoogleAccelOobTest, Read_Success)
+{
+ ::testing::StrictMock<HandlerMock> h;
+
+ constexpr char kTestDeviceName[] = "testDeviceName";
+ constexpr uint8_t kTestDeviceNameLength =
+ (sizeof(kTestDeviceName) / sizeof(*kTestDeviceName)) - 1;
+ constexpr uint8_t kTestToken = 0xAB;
+ constexpr uint64_t kTestAddress = 0;
+ constexpr uint8_t kTestReadSize = 8;
+ constexpr uint64_t kTestData = 0x12345678;
+
+ struct Request
+ {
+ uint8_t nameLength;
+ char name[kTestDeviceNameLength];
+ uint8_t token;
+ uint64_t address;
+ uint8_t num_bytes;
+ } __attribute__((packed));
+
+ struct Reply
+ {
+ uint8_t nameLength;
+ char name[kTestDeviceNameLength];
+ uint8_t token;
+ uint64_t address;
+ uint8_t num_bytes;
+ uint64_t data;
+ } __attribute__((packed));
+
+ const std::string_view kTestDeviceNameStr(kTestDeviceName,
+ kTestDeviceNameLength);
+ EXPECT_CALL(h,
+ accelOobRead(kTestDeviceNameStr, kTestAddress, kTestReadSize))
+ .WillOnce(Return(kTestData));
+
+ Request reqBuf{kTestDeviceNameLength, "", kTestToken, kTestAddress,
+ kTestReadSize};
+ memcpy(reqBuf.name, kTestDeviceName, kTestDeviceNameLength);
+ Resp r = accelOobRead(
+ std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)),
+ &h);
+
+ const auto response = std::get<0>(r);
+ EXPECT_EQ(response, IPMI_CC_OK);
+
+ const auto payload = std::get<1>(r);
+ ASSERT_EQ(payload.has_value(), true);
+ const auto payload_tuple = payload.value();
+ const auto reply_cmd = std::get<0>(payload_tuple);
+ EXPECT_EQ(reply_cmd, SysAccelOobRead);
+ const auto reply_buff = std::get<1>(payload_tuple);
+ ASSERT_GE(reply_buff.size(), sizeof(Reply));
+
+ auto* reply = reinterpret_cast<const Reply*>(reply_buff.data());
+ EXPECT_EQ(reply->nameLength, kTestDeviceNameLength);
+ EXPECT_EQ(std::string_view(reply->name, reply->nameLength),
+ kTestDeviceNameStr);
+ EXPECT_EQ(reply->token, kTestToken);
+ EXPECT_EQ(reply->address, kTestAddress);
+ EXPECT_EQ(reply->num_bytes, kTestReadSize);
+ EXPECT_EQ(reply->data, kTestData);
+}
+
+TEST(GoogleAccelOobTest, Write_Success)
+{
+ ::testing::StrictMock<HandlerMock> h;
+
+ constexpr char kTestDeviceName[] = "testDeviceName";
+ constexpr uint8_t kTestDeviceNameLength =
+ (sizeof(kTestDeviceName) / sizeof(*kTestDeviceName)) - 1;
+ constexpr uint8_t kTestToken = 0xAB;
+ constexpr uint64_t kTestAddress = 0;
+ constexpr uint8_t kTestWriteSize = 8;
+ constexpr uint64_t kTestData = 0x12345678;
+
+ struct Request
+ {
+ uint8_t nameLength;
+ char name[kTestDeviceNameLength];
+ uint8_t token;
+ uint64_t address;
+ uint8_t num_bytes;
+ uint64_t data;
+ } __attribute__((packed));
+
+ struct Reply
+ {
+ uint8_t nameLength;
+ char name[kTestDeviceNameLength];
+ uint8_t token;
+ uint64_t address;
+ uint8_t num_bytes;
+ uint64_t data;
+ } __attribute__((packed));
+
+ const std::string_view kTestDeviceNameStr(kTestDeviceName,
+ kTestDeviceNameLength);
+ EXPECT_CALL(h, accelOobWrite(kTestDeviceNameStr, kTestAddress,
+ kTestWriteSize, kTestData))
+ .WillOnce(Return());
+
+ Request reqBuf{kTestDeviceNameLength, "", kTestToken, kTestAddress,
+ kTestWriteSize, kTestData};
+ memcpy(reqBuf.name, kTestDeviceName, kTestDeviceNameLength);
+ Resp r = accelOobWrite(
+ std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)),
+ &h);
+
+ const auto response = std::get<0>(r);
+ EXPECT_EQ(response, IPMI_CC_OK);
+
+ const auto payload = std::get<1>(r);
+ ASSERT_EQ(payload.has_value(), true);
+ const auto payload_tuple = payload.value();
+ const auto reply_cmd = std::get<0>(payload_tuple);
+ EXPECT_EQ(reply_cmd, SysAccelOobWrite);
+ const auto reply_buff = std::get<1>(payload_tuple);
+ ASSERT_GE(reply_buff.size(), sizeof(Reply));
+
+ auto* reply = reinterpret_cast<const Reply*>(reply_buff.data());
+ EXPECT_EQ(reply->nameLength, kTestDeviceNameLength);
+ EXPECT_EQ(std::string_view(reply->name, reply->nameLength),
+ kTestDeviceNameStr);
+ EXPECT_EQ(reply->token, kTestToken);
+ EXPECT_EQ(reply->address, kTestAddress);
+ EXPECT_EQ(reply->num_bytes, kTestWriteSize);
+ EXPECT_EQ(reply->data, kTestData);
+}
+
+} // namespace ipmi
+} // namespace google