1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "commands.hpp" 16 #include "errors.hpp" 17 #include "google_accel_oob.hpp" 18 #include "handler_mock.hpp" 19 20 #include <ipmid/api.h> 21 22 #include <gtest/gtest.h> 23 24 namespace google 25 { 26 namespace ipmi 27 { 28 29 using ::testing::Return; 30 31 TEST(GoogleAccelOobTest, DeviceCount_Success) 32 { 33 ::testing::StrictMock<HandlerMock> h; 34 35 uint8_t reqBuf[1]; // Could be 0, but zero-length arrays are an extension 36 37 struct Reply 38 { 39 uint32_t count; 40 } __attribute__((packed)); 41 42 constexpr uint32_t kTestDeviceCount = 2; 43 44 EXPECT_CALL(h, accelOobDeviceCount()).WillOnce(Return(kTestDeviceCount)); 45 46 Resp r = accelOobDeviceCount(reqBuf, &h); 47 48 const auto response = std::get<0>(r); 49 EXPECT_EQ(response, IPMI_CC_OK); 50 51 const auto payload = std::get<1>(r); 52 ASSERT_EQ(payload.has_value(), true); 53 const auto payload_tuple = payload.value(); 54 const auto reply_cmd = std::get<0>(payload_tuple); 55 EXPECT_EQ(reply_cmd, SysAccelOobDeviceCount); 56 const auto reply_buff = std::get<1>(payload_tuple); 57 ASSERT_EQ(reply_buff.size(), sizeof(Reply)); 58 59 auto* reply = reinterpret_cast<const Reply*>(reply_buff.data()); 60 EXPECT_EQ(reply->count, kTestDeviceCount); 61 } 62 63 TEST(GoogleAccelOobTest, DeviceName_Success) 64 { 65 ::testing::StrictMock<HandlerMock> h; 66 67 struct Request 68 { 69 uint32_t index; 70 } __attribute__((packed)); 71 72 struct Reply 73 { 74 uint32_t index; 75 uint8_t length; 76 char name[1]; 77 } __attribute__((packed)); 78 79 constexpr uint32_t kTestDeviceIndex = 0; 80 const std::string kTestDeviceName("testDeviceName"); 81 82 EXPECT_CALL(h, accelOobDeviceName(kTestDeviceIndex)) 83 .WillOnce(Return(kTestDeviceName)); 84 85 Request reqBuf{kTestDeviceIndex}; 86 Resp r = accelOobDeviceName( 87 std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)), 88 &h); 89 90 const auto response = std::get<0>(r); 91 EXPECT_EQ(response, IPMI_CC_OK); 92 93 const auto payload = std::get<1>(r); 94 ASSERT_EQ(payload.has_value(), true); 95 const auto payload_tuple = payload.value(); 96 const auto reply_cmd = std::get<0>(payload_tuple); 97 EXPECT_EQ(reply_cmd, SysAccelOobDeviceName); 98 const auto reply_buff = std::get<1>(payload_tuple); 99 ASSERT_GE(reply_buff.size(), sizeof(Reply)); 100 101 auto* reply = reinterpret_cast<const Reply*>(reply_buff.data()); 102 EXPECT_EQ(reply->index, kTestDeviceIndex); 103 EXPECT_EQ(reply->length, kTestDeviceName.length()); 104 EXPECT_STREQ(reply->name, kTestDeviceName.c_str()); 105 } 106 107 TEST(GoogleAccelOobTest, Read_Success) 108 { 109 ::testing::StrictMock<HandlerMock> h; 110 111 constexpr char kTestDeviceName[] = "testDeviceName"; 112 constexpr uint8_t kTestDeviceNameLength = 113 (sizeof(kTestDeviceName) / sizeof(*kTestDeviceName)) - 1; 114 constexpr uint8_t kTestToken = 0xAB; 115 constexpr uint64_t kTestAddress = 0; 116 constexpr uint8_t kTestReadSize = 8; 117 constexpr uint64_t kTestData = 0x12345678; 118 119 struct Request 120 { 121 uint8_t nameLength; 122 char name[kTestDeviceNameLength]; 123 uint8_t token; 124 uint64_t address; 125 uint8_t num_bytes; 126 } __attribute__((packed)); 127 128 struct Reply 129 { 130 uint8_t nameLength; 131 char name[kTestDeviceNameLength]; 132 uint8_t token; 133 uint64_t address; 134 uint8_t num_bytes; 135 uint64_t data; 136 } __attribute__((packed)); 137 138 const std::string_view kTestDeviceNameStr(kTestDeviceName, 139 kTestDeviceNameLength); 140 EXPECT_CALL(h, 141 accelOobRead(kTestDeviceNameStr, kTestAddress, kTestReadSize)) 142 .WillOnce(Return(kTestData)); 143 144 Request reqBuf{kTestDeviceNameLength, "", kTestToken, kTestAddress, 145 kTestReadSize}; 146 memcpy(reqBuf.name, kTestDeviceName, kTestDeviceNameLength); 147 Resp r = accelOobRead( 148 std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)), 149 &h); 150 151 const auto response = std::get<0>(r); 152 EXPECT_EQ(response, IPMI_CC_OK); 153 154 const auto payload = std::get<1>(r); 155 ASSERT_EQ(payload.has_value(), true); 156 const auto payload_tuple = payload.value(); 157 const auto reply_cmd = std::get<0>(payload_tuple); 158 EXPECT_EQ(reply_cmd, SysAccelOobRead); 159 const auto reply_buff = std::get<1>(payload_tuple); 160 ASSERT_GE(reply_buff.size(), sizeof(Reply)); 161 162 auto* reply = reinterpret_cast<const Reply*>(reply_buff.data()); 163 EXPECT_EQ(reply->nameLength, kTestDeviceNameLength); 164 EXPECT_EQ(std::string_view(reply->name, reply->nameLength), 165 kTestDeviceNameStr); 166 EXPECT_EQ(reply->token, kTestToken); 167 EXPECT_EQ(reply->address, kTestAddress); 168 EXPECT_EQ(reply->num_bytes, kTestReadSize); 169 EXPECT_EQ(reply->data, kTestData); 170 } 171 172 TEST(GoogleAccelOobTest, Write_Success) 173 { 174 ::testing::StrictMock<HandlerMock> h; 175 176 constexpr char kTestDeviceName[] = "testDeviceName"; 177 constexpr uint8_t kTestDeviceNameLength = 178 (sizeof(kTestDeviceName) / sizeof(*kTestDeviceName)) - 1; 179 constexpr uint8_t kTestToken = 0xAB; 180 constexpr uint64_t kTestAddress = 0; 181 constexpr uint8_t kTestWriteSize = 8; 182 constexpr uint64_t kTestData = 0x12345678; 183 184 struct Request 185 { 186 uint8_t nameLength; 187 char name[kTestDeviceNameLength]; 188 uint8_t token; 189 uint64_t address; 190 uint8_t num_bytes; 191 uint64_t data; 192 } __attribute__((packed)); 193 194 struct Reply 195 { 196 uint8_t nameLength; 197 char name[kTestDeviceNameLength]; 198 uint8_t token; 199 uint64_t address; 200 uint8_t num_bytes; 201 uint64_t data; 202 } __attribute__((packed)); 203 204 const std::string_view kTestDeviceNameStr(kTestDeviceName, 205 kTestDeviceNameLength); 206 EXPECT_CALL(h, accelOobWrite(kTestDeviceNameStr, kTestAddress, 207 kTestWriteSize, kTestData)) 208 .WillOnce(Return()); 209 210 Request reqBuf{kTestDeviceNameLength, "", kTestToken, kTestAddress, 211 kTestWriteSize, kTestData}; 212 memcpy(reqBuf.name, kTestDeviceName, kTestDeviceNameLength); 213 Resp r = accelOobWrite( 214 std::span(reinterpret_cast<const uint8_t*>(&reqBuf), sizeof(Request)), 215 &h); 216 217 const auto response = std::get<0>(r); 218 EXPECT_EQ(response, IPMI_CC_OK); 219 220 const auto payload = std::get<1>(r); 221 ASSERT_EQ(payload.has_value(), true); 222 const auto payload_tuple = payload.value(); 223 const auto reply_cmd = std::get<0>(payload_tuple); 224 EXPECT_EQ(reply_cmd, SysAccelOobWrite); 225 const auto reply_buff = std::get<1>(payload_tuple); 226 ASSERT_GE(reply_buff.size(), sizeof(Reply)); 227 228 auto* reply = reinterpret_cast<const Reply*>(reply_buff.data()); 229 EXPECT_EQ(reply->nameLength, kTestDeviceNameLength); 230 EXPECT_EQ(std::string_view(reply->name, reply->nameLength), 231 kTestDeviceNameStr); 232 EXPECT_EQ(reply->token, kTestToken); 233 EXPECT_EQ(reply->address, kTestAddress); 234 EXPECT_EQ(reply->num_bytes, kTestWriteSize); 235 EXPECT_EQ(reply->data, kTestData); 236 } 237 238 } // namespace ipmi 239 } // namespace google 240