blob: 3462c058db95d307fb19d6fc4c87969502a41d7e [file] [log] [blame]
// Copyright 2024 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 "message_util.hpp"
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/error.hpp>
#include <algorithm>
#include <cstring>
#include <numeric>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using google::hoth::internal::calculateChecksum;
using google::hoth::internal::populateReqHeader;
using google::hoth::internal::ReqHeader;
using google::hoth::internal::reqLen;
using google::hoth::internal::RspHeader;
using google::hoth::internal::rspLen;
using google::hoth::internal::SUPPORTED_STRUCT_VERSION;
using sdbusplus::error::xyz::openbmc_project::control::hoth::CommandFailure;
using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;
namespace
{
void convertReq(std::vector<uint8_t>& req, const struct ReqHeader& hdr)
{
req.resize(sizeof(hdr));
std::memcpy(req.data(), &hdr, req.size());
}
void convertRsp(std::vector<uint8_t>& rsp, const struct RspHeader& hdr)
{
rsp.resize(sizeof(hdr));
std::memcpy(rsp.data(), &hdr, rsp.size());
}
} // namespace
TEST(ReqLen, empty)
{
std::vector<uint8_t> req;
EXPECT_THROW(reqLen(req), CommandFailure);
}
TEST(ReqLen, wrongStructVersion)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = 42;
convertReq(req, hdr);
EXPECT_THROW(reqLen(req), CommandFailure);
}
TEST(ReqLen, lenZero)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
convertReq(req, hdr);
EXPECT_EQ(sizeof(hdr), reqLen(req));
}
TEST(ReqLen, lenZeroTrailing)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
convertReq(req, hdr);
req.resize(req.size() + 5, 42);
EXPECT_EQ(sizeof(hdr), reqLen(req));
}
TEST(ReqLen, lenOne)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = 1;
hdr.data_len = size;
convertReq(req, hdr);
EXPECT_EQ(sizeof(hdr) + size, reqLen(req));
}
TEST(ReqLen, lenBig)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = UINT8_MAX + 9001;
hdr.data_len = size;
convertReq(req, hdr);
EXPECT_EQ(sizeof(hdr) + size, reqLen(req));
}
TEST(ReqLen, lenMax)
{
std::vector<uint8_t> req;
struct ReqHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = UINT16_MAX - sizeof(hdr);
hdr.data_len = size;
convertReq(req, hdr);
EXPECT_EQ(sizeof(hdr) + size, reqLen(req));
}
TEST(RspLen, empty)
{
std::vector<uint8_t> rsp;
EXPECT_THROW(rspLen(rsp), ResponseFailure);
}
TEST(RspLen, wrongStructVersion)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = 42;
convertRsp(rsp, hdr);
EXPECT_THROW(rspLen(rsp), ResponseFailure);
}
TEST(RspLen, lenZero)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
convertRsp(rsp, hdr);
EXPECT_EQ(sizeof(hdr), rspLen(rsp));
}
TEST(RspLen, lenZeroTrailing)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
convertRsp(rsp, hdr);
rsp.resize(rsp.size() + 5, 42);
EXPECT_EQ(sizeof(hdr), rspLen(rsp));
}
TEST(RspLen, lenOne)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = 1;
hdr.data_len = size;
convertRsp(rsp, hdr);
EXPECT_EQ(sizeof(hdr) + size, rspLen(rsp));
}
TEST(RspLen, lenBig)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = UINT8_MAX + 9001;
hdr.data_len = size;
convertRsp(rsp, hdr);
EXPECT_EQ(sizeof(hdr) + size, rspLen(rsp));
}
TEST(RspLen, lenMax)
{
std::vector<uint8_t> rsp;
struct RspHeader hdr = {};
hdr.struct_version = SUPPORTED_STRUCT_VERSION;
constexpr uint16_t size = UINT16_MAX - sizeof(hdr);
hdr.data_len = size;
convertRsp(rsp, hdr);
EXPECT_EQ(sizeof(hdr) + size, rspLen(rsp));
}
TEST(CalculateChecksum, calculateChecksumSuccess)
{
// Tests to ensure the checksummer is running correctly.
uint8_t header[] = {1, 3, 5, 7};
uint8_t body[] = {2, 4, 6, 8};
// (1 + 3 + 5 + 7) + (2 + 4 + 6 + 8) = 36
EXPECT_EQ(36, calculateChecksum(header, body));
// Now test what happens if the sum exceeds 256.
body[0] = 200;
body[1] = 202;
// (1 + 3 + 5 + 7) + (200 + 202 + 6 + 8) = 432
// 432 % 256 = 176
EXPECT_EQ(176, calculateChecksum(header, body));
}
TEST(PopulateReqHeader, populateReqHeaderSuccess)
{
ASSERT_THROW(populateReqHeader(0, 0, nullptr, 0, nullptr), CommandFailure);
// NOLINTNEXTLINE(cert-msc30-c, cert-msc50-cpp)
uint16_t command = std::rand() % UINT16_MAX;
// NOLINTNEXTLINE(cert-msc30-c, cert-msc50-cpp)
uint8_t command_version = std::rand() % UINT8_MAX;
constexpr size_t kRequestSize = 15;
std::vector<uint8_t> request(kRequestSize);
std::generate(request.begin(), request.end(), std::rand);
ReqHeader request_header;
ASSERT_NO_THROW(populateReqHeader(command, command_version, request.data(),
request.size(), &request_header));
EXPECT_EQ(request_header.struct_version, SUPPORTED_STRUCT_VERSION);
EXPECT_EQ(request_header.command, command);
EXPECT_EQ(request_header.command_version, command_version);
EXPECT_EQ(request_header.reserved, 0);
EXPECT_EQ(request_header.data_len, request.size());
EXPECT_EQ(0, calculateChecksum(
stdplus::raw::asSpan<uint8_t>(request_header), request));
}
TEST(PopulateReqHeader, PopulateRequestHeaderWithNullRequestData)
{
ReqHeader request_header;
ASSERT_NO_THROW(populateReqHeader(0xa5, 12, nullptr, 0, &request_header));
EXPECT_EQ(0,
calculateChecksum(stdplus::raw::asSpan<uint8_t>(request_header)));
}