blob: b246195dbbc3f31beb51c709c0c153fda8d438e2 [file] [edit]
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*/
#include "base.h"
#include "diagnostics.h"
#include <cstring>
#include <gtest/gtest.h>
#include <vector>
/*
* Tests for Get Diag System Config Event (Event ID 0x00)
*/
TEST(DiagPreBootTest, EncodeGetSystemConfigEventValid)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_get_system_config_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_get_system_config_event(
5, true, NSM_DIAG_CONFIG_TYPE_MB1, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
}
TEST(DiagPreBootTest, EncodeGetSystemConfigEventNull)
{
int rc =
encode_nsm_diag_get_system_config_event(5, true, 0x00, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, GetSystemConfigEventRoundTrip)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_get_system_config_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_get_system_config_event(
5, true, NSM_DIAG_CONFIG_TYPE_TEST, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class = 0xFF;
uint16_t event_state = 0xFFFF;
uint8_t config_type = 0xFF;
rc = decode_nsm_diag_get_system_config_event(
msg, eventMsg.size(), &event_class, &event_state, &config_type);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(event_class, NSM_GENERAL_EVENT_CLASS);
EXPECT_EQ(event_state, 0);
EXPECT_EQ(config_type, NSM_DIAG_CONFIG_TYPE_TEST);
}
TEST(DiagPreBootTest, DecodeGetSystemConfigEventNull)
{
uint8_t event_class;
uint16_t event_state;
uint8_t config_type;
EXPECT_EQ(decode_nsm_diag_get_system_config_event(
nullptr, 0, &event_class, &event_state, &config_type),
NSM_SW_ERROR_NULL);
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
EXPECT_EQ(decode_nsm_diag_get_system_config_event(msg, eventMsg.size(),
nullptr, &event_state,
&config_type),
NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, DecodeGetSystemConfigEventShortLength)
{
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
uint8_t event_class;
uint16_t event_state;
uint8_t config_type;
EXPECT_EQ(
decode_nsm_diag_get_system_config_event(
msg, eventMsg.size(), &event_class, &event_state, &config_type),
NSM_SW_ERROR_LENGTH);
}
/*
* Tests for Get Diag TID Config Event (Event ID 0x01)
*/
TEST(DiagPreBootTest, EncodeGetTidConfigEventValid)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_get_tid_config_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_get_tid_config_event(5, true, 0x01, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
}
TEST(DiagPreBootTest, EncodeGetTidConfigEventNull)
{
int rc = encode_nsm_diag_get_tid_config_event(5, true, 0x01, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, GetTidConfigEventRoundTrip)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_get_tid_config_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_get_tid_config_event(5, true, 0x09, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class = 0xFF;
uint16_t event_state = 0xFFFF;
uint8_t tid = 0xFF;
rc = decode_nsm_diag_get_tid_config_event(
msg, eventMsg.size(), &event_class, &event_state, &tid);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(event_class, NSM_GENERAL_EVENT_CLASS);
EXPECT_EQ(event_state, 0);
EXPECT_EQ(tid, 0x09);
}
TEST(DiagPreBootTest, DecodeGetTidConfigEventNull)
{
uint8_t event_class;
uint16_t event_state;
uint8_t tid;
EXPECT_EQ(decode_nsm_diag_get_tid_config_event(nullptr, 0, &event_class,
&event_state, &tid),
NSM_SW_ERROR_NULL);
}
/*
* Tests for Set Diag Test Result Event (Event ID 0x02)
*/
TEST(DiagPreBootTest, EncodeSetTestResultEventValid)
{
uint8_t dynamic_data[] = {0xAA, 0xBB, 0xCC, 0xDD};
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(
5, true, 0x01, NSM_DIAG_TEST_PASS, sizeof(dynamic_data),
dynamic_data, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
}
TEST(DiagPreBootTest, EncodeSetTestResultEventNull)
{
int rc = encode_nsm_diag_set_test_result_event(5, true, 0x01, 0, 0,
nullptr, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, EncodeSetTestResultEventNullDynamicData)
{
std::vector<uint8_t> eventMsg(256);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(5, true, 0x01, 0, 4,
nullptr, msg);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, SetTestResultEventRoundTrip)
{
uint8_t dynamic_data[] = {0xAA, 0xBB, 0xCC, 0xDD};
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(
5, true, 0x01, 0x0006, sizeof(dynamic_data), dynamic_data, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class = 0xFF;
uint16_t event_state = 0xFFFF;
uint8_t tid = 0xFF;
uint16_t test_error_code = 0xFFFF;
uint8_t dyn_data_size = 0xFF;
uint8_t dyn_data[4] = {};
rc = decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, dyn_data);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(event_class, NSM_GENERAL_EVENT_CLASS);
EXPECT_EQ(event_state, 0);
EXPECT_EQ(tid, 0x01);
EXPECT_EQ(test_error_code, 0x0006);
EXPECT_EQ(dyn_data_size, sizeof(dynamic_data));
EXPECT_EQ(memcmp(dyn_data, dynamic_data, sizeof(dynamic_data)), 0);
}
TEST(DiagPreBootTest, SetTestResultEventRoundTripNoDynamicData)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(
5, true, 0x02, NSM_DIAG_TEST_FAIL, 0, nullptr, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
rc = decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, nullptr);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(tid, 0x02);
EXPECT_EQ(test_error_code, NSM_DIAG_TEST_FAIL);
EXPECT_EQ(dyn_data_size, 0);
}
TEST(DiagPreBootTest, SetTestResultEventEndianness)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(5, true, 0x01, 0x1234, 0,
nullptr, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
rc = decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, nullptr);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(test_error_code, 0x1234);
}
TEST(DiagPreBootTest, DecodeSetTestResultEventNull)
{
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
EXPECT_EQ(decode_nsm_diag_set_test_result_event(
nullptr, 0, &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, nullptr),
NSM_SW_ERROR_NULL);
}
/*
* Tests for Set Diag Flow Control Event (Event ID 0x03)
*/
TEST(DiagPreBootTest, EncodeSetFlowControlEventValid)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_flow_control_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_flow_control_event(
5, false, NSM_DIAG_FLOW_CTRL_IN_PROGRESS, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
}
TEST(DiagPreBootTest, EncodeSetFlowControlEventNull)
{
int rc =
encode_nsm_diag_set_flow_control_event(5, false, 0x01, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, SetFlowControlEventRoundTrip)
{
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_flow_control_event_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_flow_control_event(
5, false, NSM_DIAG_FLOW_CTRL_EXECUTION_FINISHED, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t event_class = 0xFF;
uint16_t event_state = 0xFFFF;
uint8_t flow_ctrl_status = 0xFF;
rc = decode_nsm_diag_set_flow_control_event(msg, eventMsg.size(),
&event_class, &event_state,
&flow_ctrl_status);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(event_class, NSM_GENERAL_EVENT_CLASS);
EXPECT_EQ(event_state, 0);
EXPECT_EQ(flow_ctrl_status, NSM_DIAG_FLOW_CTRL_EXECUTION_FINISHED);
}
TEST(DiagPreBootTest, DecodeSetFlowControlEventNull)
{
uint8_t event_class;
uint16_t event_state;
uint8_t flow_ctrl_status;
EXPECT_EQ(
decode_nsm_diag_set_flow_control_event(
nullptr, 0, &event_class, &event_state, &flow_ctrl_status),
NSM_SW_ERROR_NULL);
}
/*
* Tests for Set Diag System Config Command (Command 0x80)
*/
TEST(DiagPreBootTest, EncodeSetSystemConfigReqValid)
{
uint8_t dynamic_data[] = {0x11, 0x22, 0x33};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_system_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_system_config_req(5, NSM_DIAG_CONFIG_TYPE_MB1,
0x02, dynamic_data,
sizeof(dynamic_data), msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
auto *request =
reinterpret_cast<struct nsm_diag_set_system_config_req *>(
msg->payload);
EXPECT_EQ(request->hdr.command, NSM_DIAG_SET_SYSTEM_CONFIG);
EXPECT_EQ(request->config_type, NSM_DIAG_CONFIG_TYPE_MB1);
EXPECT_EQ(request->system_test_duration, 0x02);
}
TEST(DiagPreBootTest, EncodeSetSystemConfigReqNull)
{
int rc =
encode_diag_set_system_config_req(5, 0, 0, nullptr, 0, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, SetSystemConfigReqRoundTrip)
{
uint8_t dynamic_data[] = {0x11, 0x22, 0x33};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_system_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_system_config_req(5, NSM_DIAG_CONFIG_TYPE_TEST,
0x03, dynamic_data,
sizeof(dynamic_data), msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t config_type = 0xFF;
uint8_t system_test_duration = 0xFF;
uint8_t dyn_data_size = 0xFF;
uint8_t dyn_data[3] = {};
rc = decode_diag_set_system_config_req(msg, reqMsg.size(), &config_type,
&system_test_duration,
&dyn_data_size, dyn_data);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(config_type, NSM_DIAG_CONFIG_TYPE_TEST);
EXPECT_EQ(system_test_duration, 0x03);
EXPECT_EQ(dyn_data_size, sizeof(dynamic_data));
EXPECT_EQ(memcmp(dyn_data, dynamic_data, sizeof(dynamic_data)), 0);
}
TEST(DiagPreBootTest, DecodeSetSystemConfigReqNull)
{
uint8_t config_type, duration, dyn_size;
EXPECT_EQ(decode_diag_set_system_config_req(
nullptr, 0, &config_type, &duration, &dyn_size, nullptr),
NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, DecodeSetSystemConfigReqShortLength)
{
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
uint8_t config_type, duration, dyn_size;
EXPECT_EQ(decode_diag_set_system_config_req(msg, reqMsg.size(),
&config_type, &duration,
&dyn_size, nullptr),
NSM_SW_ERROR_LENGTH);
}
/*
* Tests for Set Diag TID Config Command (Command 0x81)
*/
TEST(DiagPreBootTest, EncodeSetTidConfigReqValid)
{
uint8_t dynamic_data[] = {0xAA, 0xBB};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_tid_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(
5, 0x01, 0x02, 100, NSM_DIAG_LOG_ERROR, sizeof(dynamic_data),
dynamic_data, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
auto *request = reinterpret_cast<struct nsm_diag_set_tid_config_req *>(
msg->payload);
EXPECT_EQ(request->hdr.command, NSM_DIAG_SET_TID_CONFIG);
EXPECT_EQ(request->tid, 0x01);
EXPECT_EQ(request->tid_test_duration, 0x02);
}
TEST(DiagPreBootTest, EncodeSetTidConfigReqNull)
{
int rc =
encode_diag_set_tid_config_req(5, 0, 0, 0, 0, 0, nullptr, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, SetTidConfigReqRoundTrip)
{
uint8_t dynamic_data[] = {0xAA, 0xBB, 0xCC, 0xDD};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_tid_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(
5, 0x09, 0x03, 500, NSM_DIAG_LOG_DEBUG, sizeof(dynamic_data),
dynamic_data, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t tid = 0xFF;
uint8_t tid_test_duration = 0xFF;
uint16_t loops = 0xFFFF;
uint8_t console_log_level = 0xFF;
uint8_t dyn_data_size = 0xFF;
uint8_t dyn_data[4] = {};
rc = decode_diag_set_tid_config_req(
msg, reqMsg.size(), &tid, &tid_test_duration, &loops,
&console_log_level, &dyn_data_size, dyn_data);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(tid, 0x09);
EXPECT_EQ(tid_test_duration, 0x03);
EXPECT_EQ(loops, 500);
EXPECT_EQ(console_log_level, NSM_DIAG_LOG_DEBUG);
EXPECT_EQ(dyn_data_size, sizeof(dynamic_data));
EXPECT_EQ(memcmp(dyn_data, dynamic_data, sizeof(dynamic_data)), 0);
}
TEST(DiagPreBootTest, SetTidConfigReqEndianness)
{
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_tid_config_req) - 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(5, 0x01, 0x01, 0x1234, 0x00, 0,
nullptr, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t tid, duration, log_level, dyn_size;
uint16_t loops;
rc = decode_diag_set_tid_config_req(msg, reqMsg.size(), &tid, &duration,
&loops, &log_level, &dyn_size,
nullptr);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
EXPECT_EQ(loops, 0x1234);
}
TEST(DiagPreBootTest, DecodeSetTidConfigReqNull)
{
uint8_t tid, duration, log_level, dyn_size;
uint16_t loops;
EXPECT_EQ(decode_diag_set_tid_config_req(nullptr, 0, &tid, &duration,
&loops, &log_level, &dyn_size,
nullptr),
NSM_SW_ERROR_NULL);
}
TEST(DiagPreBootTest, DecodeSetTidConfigReqShortLength)
{
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
uint8_t tid, duration, log_level, dyn_size;
uint16_t loops;
EXPECT_EQ(decode_diag_set_tid_config_req(msg, reqMsg.size(), &tid,
&duration, &loops, &log_level,
&dyn_size, nullptr),
NSM_SW_ERROR_LENGTH);
}
/*
* Missing coverage tests
*/
TEST(DiagPreBootTest, EncodeSetTestResultEventOversizeDynamicData)
{
uint8_t bigData[NSM_DIAG_MAX_DYNAMIC_DATA_SIZE + 1] = {};
std::vector<uint8_t> eventMsg(512);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(
5, true, 0x01, 0, sizeof(bigData), bigData, msg);
EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, EncodeSetSystemConfigReqOversizeDynamicData)
{
uint8_t bigData[NSM_DIAG_MAX_DYNAMIC_DATA_SIZE + 1] = {};
std::vector<uint8_t> reqMsg(512);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_system_config_req(5, 0, 0, bigData,
sizeof(bigData), msg);
EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, EncodeSetTidConfigReqOversizeDynamicData)
{
/* TID config has a tighter cap than the event-side 251 because
* the TID command also carries 6 fixed bytes in the 256-byte budget. */
uint8_t bigData[NSM_DIAG_MAX_TID_DYNAMIC_DATA_SIZE + 1] = {};
std::vector<uint8_t> reqMsg(512);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(5, 0x01, 0, 1, 0,
sizeof(bigData), bigData, msg);
EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, EncodeSetTidConfigReqAtTidCapBoundary)
{
/* Right at the cap (244) must succeed. */
uint8_t data[NSM_DIAG_MAX_TID_DYNAMIC_DATA_SIZE] = {};
std::vector<uint8_t> reqMsg(512);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(5, 0x01, 0, 1, 0, sizeof(data),
data, msg);
EXPECT_EQ(rc, NSM_SW_SUCCESS);
}
TEST(DiagPreBootTest, DecodeGetTidConfigEventShortLength)
{
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
uint8_t event_class;
uint16_t event_state;
uint8_t tid;
EXPECT_EQ(decode_nsm_diag_get_tid_config_event(
msg, eventMsg.size(), &event_class, &event_state, &tid),
NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, DecodeSetTestResultEventShortLength)
{
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
EXPECT_EQ(decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, nullptr),
NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, DecodeSetFlowControlEventShortLength)
{
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
uint8_t event_class;
uint16_t event_state;
uint8_t flow_ctrl_status;
EXPECT_EQ(decode_nsm_diag_set_flow_control_event(
msg, eventMsg.size(), &event_class, &event_state,
&flow_ctrl_status),
NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, DecodeSetSystemConfigReqTruncatedDataSize)
{
// Build a valid-looking message but with hdr.data_size < fixed fields
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_system_config_req) - 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
// Encode a valid request first to set up headers
int rc =
encode_diag_set_system_config_req(5, 0x00, 0x01, nullptr, 0, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
// Corrupt data_size to be less than the two fixed fields
auto *request =
reinterpret_cast<struct nsm_diag_set_system_config_req *>(
msg->payload);
request->hdr.data_size =
0; // less than sizeof(config_type) + sizeof(duration)
uint8_t config_type, duration, dyn_size;
rc = decode_diag_set_system_config_req(msg, reqMsg.size(), &config_type,
&duration, &dyn_size, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_DATA);
}
TEST(DiagPreBootTest, DecodeSetSystemConfigReqOOBDynamicData)
{
// Encode a valid request with no dynamic data
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_system_config_req) - 1);
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc =
encode_diag_set_system_config_req(5, 0x00, 0x01, nullptr, 0, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
// Corrupt data_size to claim large dynamic data beyond buffer
auto *request =
reinterpret_cast<struct nsm_diag_set_system_config_req *>(
msg->payload);
request->hdr.data_size = 200; // claims 198 bytes of dynamic data
uint8_t config_type, duration, dyn_size;
uint8_t dyn_data[256] = {};
rc = decode_diag_set_system_config_req(msg, reqMsg.size(), &config_type,
&duration, &dyn_size, dyn_data);
EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH);
}
TEST(DiagPreBootTest, DecodeSetTestResultEventNullDynamicDataWithNonzeroSize)
{
// Encode a valid event with dynamic data
uint8_t dynamic_data[] = {0xAA, 0xBB};
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
int rc = encode_nsm_diag_set_test_result_event(
5, true, 0x01, 0x0000, sizeof(dynamic_data), dynamic_data, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
// Decode with NULL dynamic_data buffer — should return error
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
rc = decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
/* C1 attack vector: a crafted Set Diag Test Result event with
* data_size at the wire-level upper bound (255) and dynamic_data_size
* greater than the spec cap (251) must be rejected. Without the cap
* check the caller's stack buffer (sized to NSM_DIAG_MAX_DYNAMIC_DATA_SIZE)
* would overflow during memcpy. */
TEST(DiagPreBootTest, DecodeSetTestResultEventOverProtocolCap)
{
/* Build a buffer large enough to hold the crafted dynamic_data_size,
* so the inner data_size check passes but our new cap check fires. */
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_diag_set_test_result_event_data) - 1 + 255);
auto *msg = reinterpret_cast<struct nsm_msg *>(eventMsg.data());
/* Encode with valid (small) data first so the headers are well-formed.
*/
uint8_t small[1] = {0};
int rc = encode_nsm_diag_set_test_result_event(5, true, 0x01, 0x0000, 1,
small, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
/* Now corrupt the wire to claim 252 bytes of dynamic data. The wire
* data_size is uint8_t (max 255), so we set it to its upper bound;
* the cap check on dynamic_data_size fires before the inner
* consistency check, so this is enough to exercise the guard. */
auto *event = reinterpret_cast<struct nsm_event *>(msg->payload);
event->data_size = 255;
auto *data =
reinterpret_cast<struct nsm_diag_set_test_result_event_data *>(
event->data);
data->dynamic_data_size = 252; /* > NSM_DIAG_MAX_DYNAMIC_DATA_SIZE */
uint8_t out_buf[NSM_DIAG_MAX_DYNAMIC_DATA_SIZE] = {};
uint8_t event_class, tid, dyn_data_size;
uint16_t event_state, test_error_code;
rc = decode_nsm_diag_set_test_result_event(
msg, eventMsg.size(), &event_class, &event_state, &tid,
&test_error_code, &dyn_data_size, out_buf);
EXPECT_EQ(rc, NSM_SW_ERROR_LENGTH);
}
/* C4: decode_diag_set_system_config_req must error when dynamic_data is
* NULL but the message claims a non-zero dynamic payload. */
TEST(DiagPreBootTest, DecodeSetSystemConfigReqNullBufferWithSize)
{
uint8_t dynamic_data[] = {0x11, 0x22, 0x33};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_system_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_system_config_req(5, 0, 0x01, dynamic_data,
sizeof(dynamic_data), msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t config_type, duration, dyn_size;
rc = decode_diag_set_system_config_req(msg, reqMsg.size(), &config_type,
&duration, &dyn_size, nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}
/* C4: decode_diag_set_tid_config_req must error when dynamic_data is
* NULL but the message claims a non-zero dynamic payload. */
TEST(DiagPreBootTest, DecodeSetTidConfigReqNullBufferWithSize)
{
uint8_t dynamic_data[] = {0xAA, 0xBB};
std::vector<uint8_t> reqMsg(sizeof(nsm_msg_hdr) +
sizeof(nsm_diag_set_tid_config_req) - 1 +
sizeof(dynamic_data));
auto *msg = reinterpret_cast<struct nsm_msg *>(reqMsg.data());
int rc = encode_diag_set_tid_config_req(
5, 0x01, 0x01, 1, 0, sizeof(dynamic_data), dynamic_data, msg);
ASSERT_EQ(rc, NSM_SW_SUCCESS);
uint8_t tid, duration, log_level, dyn_size;
uint16_t loops;
rc = decode_diag_set_tid_config_req(msg, reqMsg.size(), &tid, &duration,
&loops, &log_level, &dyn_size,
nullptr);
EXPECT_EQ(rc, NSM_SW_ERROR_NULL);
}