blob: 1b4bece63192423b4e13b0475b8b21ad6f88ff28 [file]
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*
* 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 the .cpp directly so that its anonymous-namespace `commands`
// vector and all class definitions are in this translation unit.
#include "network-ports.h"
#include "pci-links.h"
#include "platform-environmental.h"
#include "powersmoothing-powerprofile-api-v2.h"
#include "../nsm_telemetry_cmd.cpp"
#include <gtest/gtest.h>
// Telemetry commands (after registerCommand) in order:
// [0] GetPortTelemetryCounter
// [1] QueryPortCharacteristics
// [2] QueryPortStatus
// [3] QueryPortsAvailable
// [4] SetPortDisableFuture
// [5] GetFabricManagerState
// [6] GetPortDisableFuture
// [7] GetPowerMode
// [8] SetPowerMode
// [9] GetSwitchIsolationMode
// [10] SetSwitchIsolationMode
// [11] GetInventoryInformation
// [12] GetTemperatureReading
// [13] ReadThermalParameter
// [14] GetCurrentPowerDraw
// [15] GetMaxObservedPower
// [16] GetCurrentEnergyCount
// [17] GetVoltage
// [18] GetAltitudePressure
// [19] GetDriverInfo
// [20] GetMigMode
// [21] SetMigMode
// [22] GetEccMode
// [23] SetEccMode
// [24] GetEccErrorCounts
// [25] SetClockLimit
// [26] GetEDPpScalingFactors
// [27] SetEDPpScalingFactors
// [28] QueryScalarGroupTelemetry
// [29] QueryVectorGroupTelemetry
// [30] QueryAvailableAndClearableScalarGroup
// [31] PcieFundamentalReset
// [32] ClearScalarDataSource
// [33] GetClockLimit
// [34] SetPowerLimit
// [35] GetPowerLimit
// [36] GetCurrClockFreq
// [37] GetAccumGpuUtilTime
// [38] GetProcessorThrottleReason
// [39] GetRowRemapState
// [40] GetRowRemappingCounts
// [41] GetRowRemapAvailability
// [42] GetLeakDetectionInfo
// [43] SetLeakDetectionThresholds
// [44] GetMemoryCapacityUtil
// [45] GetCurrentUtilization
// [46] GetClockOutputEnableState
// [47] GetSupportedGPMMetrics
// [48] QueryAggregatedGPMMetrics
// [49] QueryPerInstanceGPMMetrics
// [50] QueryPerInstanceGPMMetricsV2
// [51] GetViolationDuration
// [52] GetListAvailablePciePorts
// [53] GetPCIePortConfig
// [54] SetPCIePortConfig
// [55] QueryMultiportScalarGroupTelemetry
// [56] GetEthPortTelemetryCounter
// [57] GetPortNetworkAddresses
// [58] GetPortEccCounters
// [59] GetPowerSmoothingFeatureInfoV2
// [60] GetPowerSmoothingCurrentProfileInformationV2
// [61] GetPowerSmoothingAdminOverrideProfileInformationV2
// [62] GetPowerSmoothingPresetProfileInformationV2
namespace nsmtool::telemetry
{
// ---- Helpers ----------------------------------------------------------------
static void setupTelemetryCommands(CLI::App& app)
{
commands.clear();
registerCommand(app);
}
static void parseSubcmdArgs(CLI::App& app, const std::string& cmdName,
std::vector<std::string> extraArgs = {})
{
auto* telSub = app.get_subcommand("telemetry");
if (!telSub)
return;
auto* leafSub = telSub->get_subcommand(cmdName);
if (!leafSub)
return;
std::vector<std::string> args = {"-m", "1"};
args.insert(args.end(), extraArgs.begin(), extraArgs.end());
std::reverse(args.begin(), args.end());
try
{
leafSub->parse(args);
}
catch (...)
{}
}
// Helper: build a minimal aggregate response (0 samples)
static std::vector<uint8_t> makeAggregateResp(uint8_t cmd)
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, cmd, NSM_SUCCESS, 0, msg);
return buf;
}
// ---- [0] GetPortTelemetryCounter --------------------------------------------
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
struct nsm_port_counter_data portData{};
// nsm_get_port_telemetry_counter_resp has data[1] so allocate for full
// counter data
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp) +
sizeof(nsm_port_counter_data));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_port_telemetry_counter_resp(0, NSM_SUCCESS, ERR_NULL, &portData,
msg);
EXPECT_NO_THROW(commands[0]->parseResponseMsg(msg, buf.size()));
}
// ---- [1] QueryPortCharacteristics -------------------------------------------
TEST(NsmTelemetryCmdParse, QueryPortCharacteristics_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPortCharacteristics", {"-p", "0"});
struct nsm_port_characteristics_data charData{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_query_port_characteristics_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_port_characteristics_resp(0, NSM_SUCCESS, ERR_NULL, &charData,
msg);
EXPECT_NO_THROW(commands[1]->parseResponseMsg(msg, buf.size()));
}
// ---- [2] QueryPortStatus ----------------------------------------------------
TEST(NsmTelemetryCmdParse, QueryPortStatus_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPortStatus", {"-p", "0"});
uint8_t portState = NSM_PORTSTATE_UP;
uint8_t portStatus = NSM_PORTSTATUS_ENABLED;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_query_port_status_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_port_status_resp(0, NSM_SUCCESS, ERR_NULL, portState,
portStatus, msg);
EXPECT_NO_THROW(commands[2]->parseResponseMsg(msg, buf.size()));
}
// ---- [3] QueryPortsAvailable ------------------------------------------------
TEST(NsmTelemetryCmdParse, QueryPortsAvailable_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_query_ports_available_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_ports_available_resp(0, NSM_SUCCESS, ERR_NULL, 1, msg);
EXPECT_NO_THROW(commands[3]->parseResponseMsg(msg, buf.size()));
}
// ---- [4] SetPortDisableFuture -----------------------------------------------
TEST(NsmTelemetryCmdParse, SetPortDisableFuture_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPortDisableFuture",
{"-p", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_port_disable_future_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[4]->parseResponseMsg(msg, buf.size()));
}
// ---- [5] GetFabricManagerState ----------------------------------------------
TEST(NsmTelemetryCmdParse, GetFabricManagerState_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_fabric_manager_state_data fmData{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_fabric_manager_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_fabric_manager_state_resp(0, NSM_SUCCESS, ERR_NULL, &fmData,
msg);
EXPECT_NO_THROW(commands[5]->parseResponseMsg(msg, buf.size()));
}
// ---- [6] GetPortDisableFuture -----------------------------------------------
TEST(NsmTelemetryCmdParse, GetPortDisableFuture_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t portMask[PORT_MASK_DATA_SIZE]{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_port_disable_future_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_port_disable_future_resp(0, NSM_SUCCESS, ERR_NULL, portMask,
msg);
EXPECT_NO_THROW(commands[6]->parseResponseMsg(msg, buf.size()));
}
// ---- [7] GetPowerMode -------------------------------------------------------
TEST(NsmTelemetryCmdParse, GetPowerMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_power_mode_data pmData{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_power_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_power_mode_resp(0, NSM_SUCCESS, ERR_NULL, &pmData, msg);
EXPECT_NO_THROW(commands[7]->parseResponseMsg(msg, buf.size()));
}
// ---- [8] SetPowerMode -------------------------------------------------------
TEST(NsmTelemetryCmdParse, SetPowerMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPowerMode",
{"-C", "0", "-T", "0", "-P", "0", "-t", "0", "-a", "0",
"-i", "0", "-p", "0"});
// encode_set_power_mode_resp has no cc parameter
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_power_mode_resp(0, ERR_NULL, msg);
EXPECT_NO_THROW(commands[8]->parseResponseMsg(msg, buf.size()));
}
// ---- [9] GetSwitchIsolationMode ---------------------------------------------
TEST(NsmTelemetryCmdParse, GetSwitchIsolationMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_switch_isolation_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_switch_isolation_mode_resp(0, NSM_SUCCESS, ERR_NULL, 0, msg);
EXPECT_NO_THROW(commands[9]->parseResponseMsg(msg, buf.size()));
}
// ---- [10] SetSwitchIsolationMode --------------------------------------------
TEST(NsmTelemetryCmdParse, SetSwitchIsolationMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetSwitchIsolationMode", {"-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_switch_isolation_mode_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[10]->parseResponseMsg(msg, buf.size()));
}
// ---- [11] GetInventoryInformation -------------------------------------------
TEST(NsmTelemetryCmdParse, GetInventoryInformation_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "0"});
// propertyId=0 = BOARD_PART_NUMBER (string type)
const char* partNumber = "TEST-PART-NUM";
uint16_t dataSize = static_cast<uint16_t>(strlen(partNumber));
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(
0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<const uint8_t*>(partNumber), msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// ---- [12] GetTemperatureReading (sensorId=255 -> aggregate) -----------------
TEST(NsmTelemetryCmdParse, GetTemperatureReading_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
auto buf = makeAggregateResp(NSM_GET_TEMPERATURE_READING);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [12] GetTemperatureReading (sensorId=0 -> regular) --------------------
TEST(NsmTelemetryCmdParse, GetTemperatureReading_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_temperature_reading_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
double temp = 25.0;
encode_get_temperature_reading_resp(0, NSM_SUCCESS, ERR_NULL, temp, msg);
EXPECT_NO_THROW(commands[12]->parseResponseMsg(msg, buf.size()));
}
// ---- [13] ReadThermalParameter (sensorId=255 -> aggregate) -----------------
TEST(NsmTelemetryCmdParse, ReadThermalParameter_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "ReadThermalParameter", {"-s", "255"});
auto buf = makeAggregateResp(NSM_READ_THERMAL_PARAMETER);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[13]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [13] ReadThermalParameter (sensorId=0 -> regular) ---------------------
TEST(NsmTelemetryCmdParse, ReadThermalParameter_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "ReadThermalParameter", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_read_thermal_parameter_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
int32_t threshold = 100;
encode_read_thermal_parameter_resp(0, NSM_SUCCESS, ERR_NULL, threshold,
msg);
EXPECT_NO_THROW(commands[13]->parseResponseMsg(msg, buf.size()));
}
// ---- [14] GetCurrentPowerDraw (sensorId=255 -> aggregate) ------------------
TEST(NsmTelemetryCmdParse, GetCurrentPowerDraw_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentPowerDraw", {"-s", "255"});
auto buf = makeAggregateResp(NSM_GET_POWER);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[14]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [14] GetCurrentPowerDraw (sensorId=0 -> regular) ----------------------
TEST(NsmTelemetryCmdParse, GetCurrentPowerDraw_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentPowerDraw", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_power_draw_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
uint32_t reading = 150000;
encode_get_current_power_draw_resp(0, NSM_SUCCESS, ERR_NULL, reading, msg);
EXPECT_NO_THROW(commands[14]->parseResponseMsg(msg, buf.size()));
}
// ---- [15] GetMaxObservedPower (sensorId=255 -> aggregate) ------------------
TEST(NsmTelemetryCmdParse, GetMaxObservedPower_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetMaxObservedPower", {"-s", "255"});
auto buf = makeAggregateResp(NSM_GET_MAX_OBSERVED_POWER);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[15]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [15] GetMaxObservedPower (sensorId=0 -> regular) ----------------------
TEST(NsmTelemetryCmdParse, GetMaxObservedPower_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetMaxObservedPower", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_power_draw_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
uint32_t reading = 200000;
encode_get_max_observed_power_resp(0, NSM_SUCCESS, ERR_NULL, reading, msg);
EXPECT_NO_THROW(commands[15]->parseResponseMsg(msg, buf.size()));
}
// ---- [16] GetCurrentEnergyCount (sensorId=255 -> aggregate) ----------------
TEST(NsmTelemetryCmdParse, GetCurrentEnergyCount_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentEnergyCount", {"-s", "255"});
auto buf = makeAggregateResp(NSM_GET_ENERGY_COUNT);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[16]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [16] GetCurrentEnergyCount (sensorId=0 -> regular) --------------------
TEST(NsmTelemetryCmdParse, GetCurrentEnergyCount_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentEnergyCount", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_energy_count_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
uint64_t reading = 123456789;
encode_get_current_energy_count_resp(0, NSM_SUCCESS, ERR_NULL, reading,
msg);
EXPECT_NO_THROW(commands[16]->parseResponseMsg(msg, buf.size()));
}
// ---- [17] GetVoltage (sensorId=255 -> aggregate) ---------------------------
TEST(NsmTelemetryCmdParse, GetVoltage_Aggregate_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetVoltage", {"-s", "255"});
auto buf = makeAggregateResp(NSM_GET_VOLTAGE);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[17]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [17] GetVoltage (sensorId=0 -> regular) --------------------------------
TEST(NsmTelemetryCmdParse, GetVoltage_Regular_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetVoltage", {"-s", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_voltage_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
uint32_t reading = 1200;
encode_get_voltage_resp(0, NSM_SUCCESS, ERR_NULL, reading, msg);
EXPECT_NO_THROW(commands[17]->parseResponseMsg(msg, buf.size()));
}
// ---- [18] GetAltitudePressure -----------------------------------------------
TEST(NsmTelemetryCmdParse, GetAltitudePressure_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_altitude_pressure_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
uint32_t reading = 101325;
encode_get_altitude_pressure_resp(0, NSM_SUCCESS, ERR_NULL, reading, msg);
EXPECT_NO_THROW(commands[18]->parseResponseMsg(msg, buf.size()));
}
// ---- [19] GetDriverInfo -----------------------------------------------------
TEST(NsmTelemetryCmdParse, GetDriverInfo_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
const char* version = "550.00.00";
uint16_t dataSize = 1 + static_cast<uint16_t>(strlen(version) + 1);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_driver_info_resp) +
strlen(version));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
// driver_info_data: first byte = driver_state, remaining = version string
std::vector<uint8_t> driverInfoData(dataSize, 0);
driverInfoData[0] = static_cast<uint8_t>(DriverStateEnum::DriverLoaded);
memcpy(driverInfoData.data() + 1, version, strlen(version));
encode_get_driver_info_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
driverInfoData.data(), msg);
EXPECT_NO_THROW(commands[19]->parseResponseMsg(msg, buf.size()));
}
// ---- [20] GetMigMode --------------------------------------------------------
TEST(NsmTelemetryCmdParse, GetMigMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_MIG_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_MIG_mode_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[20]->parseResponseMsg(msg, buf.size()));
}
// ---- [21] SetMigMode --------------------------------------------------------
TEST(NsmTelemetryCmdParse, SetMigMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetMigModes", {"-r", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_MIG_mode_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[21]->parseResponseMsg(msg, buf.size()));
}
// ---- [22] GetEccMode --------------------------------------------------------
TEST(NsmTelemetryCmdParse, GetEccMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_ECC_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_ECC_mode_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[22]->parseResponseMsg(msg, buf.size()));
}
// ---- [23] SetEccMode --------------------------------------------------------
TEST(NsmTelemetryCmdParse, SetEccMode_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetEccMode", {"-r", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_ECC_mode_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[23]->parseResponseMsg(msg, buf.size()));
}
// ---- [24] GetEccErrorCounts -------------------------------------------------
TEST(NsmTelemetryCmdParse, GetEccErrorCounts_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_ECC_error_counts errorCounts{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_ECC_error_counts_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_ECC_error_counts_resp(0, NSM_SUCCESS, ERR_NULL, &errorCounts,
msg);
EXPECT_NO_THROW(commands[24]->parseResponseMsg(msg, buf.size()));
}
// ---- [25] SetClockLimit -----------------------------------------------------
TEST(NsmTelemetryCmdParse, SetClockLimit_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetClockLimit",
{"-c", "0", "-f", "0", "-a", "100", "-b", "200"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_clock_limit_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[25]->parseResponseMsg(msg, buf.size()));
}
// ---- [26] GetEDPpScalingFactors ---------------------------------------------
TEST(NsmTelemetryCmdParse, GetEDPpScalingFactors_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_EDPp_scaling_factors sf{};
sf.persistent_scaling_factor = 80;
sf.oneshot_scaling_factor = 90;
sf.enforced_scaling_factor = 85;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_programmable_EDPp_scaling_factor_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_programmable_EDPp_scaling_factor_resp(0, NSM_SUCCESS, ERR_NULL,
&sf, msg);
EXPECT_NO_THROW(commands[26]->parseResponseMsg(msg, buf.size()));
}
// ---- [27] SetEDPpScalingFactors ---------------------------------------------
TEST(NsmTelemetryCmdParse, SetEDPpScalingFactors_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetEDPpScalingFactors",
{"-a", "0", "-p", "0", "-s", "100"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_programmable_EDPp_scaling_factor_resp(0, NSM_SUCCESS, ERR_NULL,
msg);
EXPECT_NO_THROW(commands[27]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 0)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group0_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "0"});
struct nsm_query_scalar_group_telemetry_group_0 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_0_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group0_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 1)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group1_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "1"});
struct nsm_query_scalar_group_telemetry_group_1 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_1_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group1_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 2)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "2"});
struct nsm_query_scalar_group_telemetry_group_2 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_2_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group2_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 3)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group3_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "3"});
struct nsm_query_scalar_group_telemetry_group_3 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_3_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group3_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 4)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group4_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "4"});
struct nsm_query_scalar_group_telemetry_group_4 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_4_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group4_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 5)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group5_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "5"});
struct nsm_query_scalar_group_telemetry_group_5 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_5_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group5_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 6)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group6_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "6"});
struct nsm_query_scalar_group_telemetry_group_6 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_6_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group6_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 8)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group8_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "8"});
struct nsm_query_scalar_group_telemetry_group_8 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_8_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group8_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 9)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group9_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "9"});
struct nsm_query_scalar_group_telemetry_group_9 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_9_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group9_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 10)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group10_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "10"});
struct nsm_query_scalar_group_telemetry_group_10 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_10_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group10_resp(0, NSM_SUCCESS,
ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (group 10 extended / 56-byte)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryScalarGroupTelemetry_Group10Extended_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "10"});
struct nsm_query_scalar_group_telemetry_group_10_extended data{};
data.outbound_read_tlp_count = 1;
data.dwords_transferred_in_outbound_read_tlp_high = 2;
data.dwords_transferred_in_outbound_read_tlp_low = 3;
data.outbound_write_tlp_count = 4;
data.dwords_transferred_in_outbound_write_tlp_high = 5;
data.dwords_transferred_in_outbound_write_tlp_low = 6;
data.outbound_completion_tlp_count = 7;
data.dwords_transferred_in_outbound_completion = 8;
data.read_requests_dropped_tag_unavailable = 9;
data.read_requests_dropped_credit_exhaustion = 10;
data.read_requests_dropped_credit_not_posted = 11;
data.inbound_completion_tlp_count = 12;
data.inbound_completion_tlp_bytes_high = 13;
data.inbound_completion_tlp_bytes_low = 14;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_10_extended_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group10_extended_resp(
0, NSM_SUCCESS, ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [55] QueryMultiportScalarGroupTelemetry (group 10 legacy / 44-byte)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryMultiportScalarGroupTelemetry_Group10_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryMultiportScalarGroupTelemetry",
{"-d", "0", "-g", "10", "-t", "0", "-u", "0", "-i", "0"});
struct nsm_query_scalar_group_telemetry_group_10 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_10_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group10_resp(0, NSM_SUCCESS,
ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[55]->parseResponseMsg(msg, buf.size()));
}
// ---- [55] QueryMultiportScalarGroupTelemetry (group 10 extended / 56-byte)
// --------------------------------
TEST(NsmTelemetryCmdParse,
QueryMultiportScalarGroupTelemetry_Group10Extended_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryMultiportScalarGroupTelemetry",
{"-d", "0", "-g", "10", "-t", "0", "-u", "0", "-i", "0"});
struct nsm_query_scalar_group_telemetry_group_10_extended data{};
data.outbound_read_tlp_count = 1;
data.dwords_transferred_in_outbound_read_tlp_high = 2;
data.dwords_transferred_in_outbound_read_tlp_low = 3;
data.outbound_write_tlp_count = 4;
data.dwords_transferred_in_outbound_write_tlp_high = 5;
data.dwords_transferred_in_outbound_write_tlp_low = 6;
data.outbound_completion_tlp_count = 7;
data.dwords_transferred_in_outbound_completion = 8;
data.read_requests_dropped_tag_unavailable = 9;
data.read_requests_dropped_credit_exhaustion = 10;
data.read_requests_dropped_credit_not_posted = 11;
data.inbound_completion_tlp_count = 12;
data.inbound_completion_tlp_bytes_high = 13;
data.inbound_completion_tlp_bytes_low = 14;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_10_extended_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group10_extended_resp(
0, NSM_SUCCESS, ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[55]->parseResponseMsg(msg, buf.size()));
}
// ---- [28] QueryScalarGroupTelemetry (unknown group -> default case)
// ----------
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_UnknownGroup)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- [29] QueryVectorGroupTelemetry (group 1) -------------------------------
TEST(NsmTelemetryCmdParse,
QueryVectorGroupTelemetry_Group1_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(
app, "QueryVectorGroupTelemetry",
{"-t", "0", "-u", "0", "-i", "0", "-g", "1", "-s", "1", "-l", "0"});
nsm_query_vector_group_1_data data{};
data.cdr_error_per_lane = 42;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_query_vector_data_sources_v2_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_vector_group_telemetry_v2_group1_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[29]->parseResponseMsg(msg, buf.size()));
}
// ---- [29] QueryVectorGroupTelemetry (invalid group -> default case) ---------
TEST(NsmTelemetryCmdParse, QueryVectorGroupTelemetry_InvalidGroup)
{
CLI::App app;
setupTelemetryCommands(app);
// groupId=2 hits the default case in the switch statement
parseSubcmdArgs(
app, "QueryVectorGroupTelemetry",
{"-t", "0", "-u", "0", "-i", "0", "-g", "2", "-s", "1", "-l", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[29]->parseResponseMsg(msg, buf.size()));
}
// ---- [30] QueryAvailableAndClearableScalarGroup (group 2) -------------------
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "2"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
// +1 because data[1] in the struct only holds 1 byte but we need
// mask_length bytes for available + mask_length bytes for clearable = 2
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- [30] QueryAvailableAndClearableScalarGroup (group 3) -------------------
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group3_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "3"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- [30] QueryAvailableAndClearableScalarGroup (group 4) -------------------
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group4_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "4"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- [30] QueryAvailableAndClearableScalarGroup (default group)
// --------------
TEST(NsmTelemetryCmdParse, QueryAvailableAndClearableScalarGroup_DefaultGroup)
{
CLI::App app;
setupTelemetryCommands(app);
// groupId=1 hits the default case (invalid) in the switch statement
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- [31] PcieFundamentalReset ----------------------------------------------
TEST(NsmTelemetryCmdParse, PcieFundamentalReset_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "PcieFundamentalReset", {"-d", "0", "-a", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_assert_pcie_fundamental_reset_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[31]->parseResponseMsg(msg, buf.size()));
}
// ---- [32] ClearScalarDataSource ---------------------------------------------
TEST(NsmTelemetryCmdParse, ClearScalarDataSource_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "ClearScalarDataSource",
{"-d", "0", "-g", "2", "-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_clear_data_source_v1_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[32]->parseResponseMsg(msg, buf.size()));
}
// ---- [33] GetClockLimit -----------------------------------------------------
TEST(NsmTelemetryCmdParse, GetClockLimit_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockLimit", {"-c", "0"});
struct nsm_clock_limit clockLimit{};
clockLimit.present_limit_min = 100;
clockLimit.present_limit_max = 1000;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_limit_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_limit_resp(0, NSM_SUCCESS, ERR_NULL, &clockLimit, msg);
EXPECT_NO_THROW(commands[33]->parseResponseMsg(msg, buf.size()));
}
// ---- [33] GetClockLimit (SpeedLocked case) ----------------------------------
TEST(NsmTelemetryCmdParse, GetClockLimit_SpeedLocked_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockLimit", {"-c", "0"});
struct nsm_clock_limit clockLimit{};
// present_limit_min == present_limit_max -> SpeedLocked = true
clockLimit.present_limit_min = 1000;
clockLimit.present_limit_max = 1000;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_limit_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_limit_resp(0, NSM_SUCCESS, ERR_NULL, &clockLimit, msg);
EXPECT_NO_THROW(commands[33]->parseResponseMsg(msg, buf.size()));
}
// ---- [34] SetPowerLimit -----------------------------------------------------
TEST(NsmTelemetryCmdParse, SetPowerLimit_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPowerLimit",
{"-i", "0", "-a", "0", "-p", "0", "-l", "100000"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_power_limit_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[34]->parseResponseMsg(msg, buf.size()));
}
// ---- [35] GetPowerLimit -----------------------------------------------------
TEST(NsmTelemetryCmdParse, GetPowerLimit_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPowerLimit", {"-i", "0"});
uint32_t persistentLimit = 300000;
uint32_t oneShotLimit = 400000;
uint32_t enforcedLimit = 300000;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_power_limit_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_power_limit_resp(0, NSM_SUCCESS, ERR_NULL, persistentLimit,
oneShotLimit, enforcedLimit, msg);
EXPECT_NO_THROW(commands[35]->parseResponseMsg(msg, buf.size()));
}
// ---- [36] GetCurrClockFreq --------------------------------------------------
TEST(NsmTelemetryCmdParse, GetCurrClockFreq_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrClockFreq", {"-c", "0"});
uint32_t clockFreq = 1200;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_curr_clock_freq_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_curr_clock_freq_resp(0, NSM_SUCCESS, ERR_NULL, &clockFreq, msg);
EXPECT_NO_THROW(commands[36]->parseResponseMsg(msg, buf.size()));
}
// ---- [37] GetAccumGpuUtilTime -----------------------------------------------
TEST(NsmTelemetryCmdParse, GetAccumGpuUtilTime_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
uint32_t contextUtil = 12345;
uint32_t smUtil = 67890;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_accum_GPU_util_time_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_accum_GPU_util_time_resp(0, NSM_SUCCESS, ERR_NULL, &contextUtil,
&smUtil, msg);
EXPECT_NO_THROW(commands[37]->parseResponseMsg(msg, buf.size()));
}
// ---- [38] GetProcessorThrottleReason ----------------------------------------
TEST(NsmTelemetryCmdParse, GetProcessorThrottleReason_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield32_t flags{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_clock_event_reason_code_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_current_clock_event_reason_code_resp(0, NSM_SUCCESS, ERR_NULL,
&flags, msg);
EXPECT_NO_THROW(commands[38]->parseResponseMsg(msg, buf.size()));
}
// ---- [39] GetRowRemapState --------------------------------------------------
TEST(NsmTelemetryCmdParse, GetRowRemapState_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_row_remap_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_row_remap_state_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[39]->parseResponseMsg(msg, buf.size()));
}
// ---- [40] GetRowRemappingCounts ---------------------------------------------
TEST(NsmTelemetryCmdParse, GetRowRemappingCounts_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
uint32_t correctable = 0;
uint32_t uncorrectable = 0;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_row_remapping_counts_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_row_remapping_counts_resp(0, NSM_SUCCESS, ERR_NULL, correctable,
uncorrectable, msg);
EXPECT_NO_THROW(commands[40]->parseResponseMsg(msg, buf.size()));
}
// ---- [41] GetRowRemapAvailability -------------------------------------------
TEST(NsmTelemetryCmdParse, GetRowRemapAvailability_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_row_remap_availability remapData{};
remapData.high_remapping = 100;
remapData.low_remapping = 50;
remapData.partial_remapping = 75;
remapData.no_remapping = 25;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_row_remap_availability_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_row_remap_availability_resp(0, NSM_SUCCESS, ERR_NULL, &remapData,
msg);
EXPECT_NO_THROW(commands[41]->parseResponseMsg(msg, buf.size()));
}
// ---- [42] GetLeakDetectionInfo ----------------------------------------------
TEST(NsmTelemetryCmdParse, GetLeakDetectionInfo_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
// Encode response with 0 sensors
uint8_t numSensors = 0;
uint8_t numThresholdLevels = 0;
std::vector<uint8_t> sensorsData{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_leak_detection_info_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_leak_detection_info_resp(0, NSM_SUCCESS, ERR_NULL, numSensors,
numThresholdLevels, sensorsData.data(),
sensorsData.size(), msg);
EXPECT_NO_THROW(commands[42]->parseResponseMsg(msg, buf.size()));
}
// ---- [43] SetLeakDetectionThresholds ----------------------------------------
TEST(NsmTelemetryCmdParse, SetLeakDetectionThresholds_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetLeakDetectionThresholds",
{"-s", "0", "-n", "1", "-t", "100"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_leak_detection_thresholds_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[43]->parseResponseMsg(msg, buf.size()));
}
// ---- [44] GetMemoryCapacityUtil ---------------------------------------------
TEST(NsmTelemetryCmdParse, GetMemoryCapacityUtil_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_memory_capacity_utilization data{};
data.used_memory = 8192;
data.reserved_memory = 1024;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_memory_capacity_util_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_memory_capacity_util_resp(0, NSM_SUCCESS, ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[44]->parseResponseMsg(msg, buf.size()));
}
// ---- [45] GetCurrentUtilization ---------------------------------------------
TEST(NsmTelemetryCmdParse, GetCurrentUtilization_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
nsm_get_current_utilization_data data{};
data.gpu_utilization = 75;
data.memory_utilization = 50;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_utilization_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_current_utilization_resp(0, NSM_SUCCESS, ERR_NULL, &data, msg);
EXPECT_NO_THROW(commands[45]->parseResponseMsg(msg, buf.size()));
}
// ---- [46] GetClockOutputEnableState -----------------------------------------
TEST(NsmTelemetryCmdParse, GetClockOutputEnableState_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockOutputEnableState", {"-i", "0x80"});
uint32_t clkBuf = 0;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_output_enabled_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_output_enable_state_resp(0, NSM_SUCCESS, ERR_NULL, clkBuf,
msg);
EXPECT_NO_THROW(commands[46]->parseResponseMsg(msg, buf.size()));
}
// ---- [47] GetSupportedGPMMetrics --------------------------------------------
TEST(NsmTelemetryCmdParse, GetSupportedGPMMetrics_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetSupportedGPMMetrics", {"-t", "0"});
uint8_t bitmask[1] = {0};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_supported_gpm_metrics_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_supported_gpm_metrics_resp(0, NSM_SUCCESS, ERR_NULL, 0, 0,
bitmask, msg);
EXPECT_NO_THROW(commands[47]->parseResponseMsg(msg, buf.size()));
}
// ---- [48] QueryAggregatedGPMMetrics (aggregate response) --------------------
TEST(NsmTelemetryCmdParse, QueryAggregatedGPMMetrics_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAggregatedGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-b", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[48]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [49] QueryPerInstanceGPMMetrics ----------------------------------------
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetrics_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPerInstanceGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-d", "1", "-b", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[49]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [50] QueryPerInstanceGPMMetricsV2 --------------------------------------
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetricsV2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPerInstanceGPMMetricsV2",
{"-r", "0", "-g", "0", "-c", "0", "-d", "1", "-b", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[50]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [51] GetViolationDuration ----------------------------------------------
TEST(NsmTelemetryCmdParse, GetViolationDuration_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_violation_duration vd{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_violation_duration_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_violation_duration_resp(0, NSM_SUCCESS, ERR_NULL, &vd, msg);
EXPECT_NO_THROW(commands[51]->parseResponseMsg(msg, buf.size()));
}
// ---- [52] GetListAvailablePciePorts -----------------------------------------
TEST(NsmTelemetryCmdParse, GetListAvailablePciePorts_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
struct nsm_list_available_pcie_ports_info info{};
info.ports_count = 0;
std::vector<uint8_t> buf(NSM_LIST_AVAILABLE_PCIE_PORTS_RESPONSE_MIN_LEN);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_list_available_pcie_ports_resp(0, NSM_SUCCESS, ERR_NULL, &info, msg);
EXPECT_NO_THROW(commands[52]->parseResponseMsg(msg, buf.size()));
}
// ---- [53] GetPCIePortConfig (aggregate response) ----------------------------
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[53]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [54] SetPCIePortConfig -------------------------------------------------
TEST(NsmTelemetryCmdParse, SetPCIePortConfig_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0", "-c", "0", "-d", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_set_port_config_aggregate_resp(0, NSM_SUCCESS, ERR_NULL, msg);
EXPECT_NO_THROW(commands[54]->parseResponseMsg(msg, buf.size()));
}
// ---- [55] QueryMultiportScalarGroupTelemetry (group 0) ----------------------
TEST(NsmTelemetryCmdParse,
QueryMultiportScalarGroupTelemetry_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryMultiportScalarGroupTelemetry",
{"-d", "0", "-g", "0", "-t", "0", "-u", "0", "-i", "0"});
struct nsm_query_scalar_group_telemetry_group_0 data{};
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_0_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group0_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[55]->parseResponseMsg(msg, buf.size()));
}
// ---- [56] GetEthPortTelemetryCounter (aggregate response) -------------------
TEST(NsmTelemetryCmdParse, GetEthPortTelemetryCounter_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetEthPortTelemetryCounter", {"-p", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[56]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [57] GetPortNetworkAddresses (aggregate response) ----------------------
TEST(NsmTelemetryCmdParse, GetPortNetworkAddresses_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortNetworkAddresses", {"-p", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[57]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [58] GetPortEccCounters (aggregate response) ---------------------------
TEST(NsmTelemetryCmdParse, GetPortEccCounters_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortEccCounters", {"-p", "0"});
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[58]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [59] GetPowerSmoothingFeatureInfoV2 (aggregate response) ---------------
TEST(NsmTelemetryCmdParse, GetPowerSmoothingFeatureInfoV2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[59]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [60] GetPowerSmoothingCurrentProfileInformationV2 (aggregate) ----------
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingCurrentProfileInformationV2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[60]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [61] GetPowerSmoothingAdminOverrideProfileInformationV2 (aggregate) ----
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingAdminOverrideProfileInformationV2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[61]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- [62] GetPowerSmoothingPresetProfileInformationV2 (aggregate) -----------
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingPresetProfileInformationV2_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeAggregateResp(0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[62]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// Helper: build aggregate response with a single temperature sample
static std::vector<uint8_t>
makeAggregateRespWithTempSample(uint8_t cmd, uint8_t sensorId, double temp)
{
// Start with aggregate header (telemetry_count=1)
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, cmd, NSM_SUCCESS, 1, msg);
// Encode the temperature sample data
std::array<uint8_t, 50> sampleBuf{};
auto* nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sampleBuf.data());
uint8_t reading[8]{};
size_t consumed_len{};
encode_aggregate_temperature_reading_data(temp, reading, &consumed_len);
size_t sample_len{};
encode_aggregate_resp_sample(sensorId, true, reading, consumed_len,
nsm_sample, &sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
return buf;
}
// Helper: build aggregate response with timestamp + 1 temperature sample
static std::vector<uint8_t>
makeAggregateRespWithTimestampAndSample(uint8_t cmd, uint8_t sensorId,
double temp)
{
// telemetry_count=2 (timestamp + data sample)
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, cmd, NSM_SUCCESS, 2, msg);
std::array<uint8_t, 50> sampleBuf{};
auto* nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sampleBuf.data());
uint8_t reading[8]{};
size_t consumed_len{};
size_t sample_len{};
// Timestamp sample (tag=0xFF)
uint64_t timestamp = 1700000000ULL;
encode_aggregate_timestamp_data(timestamp, reading, &consumed_len);
encode_aggregate_resp_sample(0xFF, true, reading, consumed_len, nsm_sample,
&sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
// Temperature data sample
encode_aggregate_temperature_reading_data(temp, reading, &consumed_len);
encode_aggregate_resp_sample(sensorId, true, reading, consumed_len,
nsm_sample, &sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
return buf;
}
// ---- GetInventoryInformation variants for uncovered property IDs
// -------------
// uint32_t property: MAXIMUM_MEMORY_CAPACITY=7
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MAXIMUM_MEMORY_CAPACITY)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "7"});
uint32_t value = htole32(4096);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: GPU_HOST_ID=34 (Data = le32toh(value) + 1)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_GPU_HOST_ID)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "34"});
uint32_t value = htole32(1);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// UUID property: DEVICE_GUID=10 (UUID_INT_SIZE=16 bytes)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_UUID_DEVICE_GUID)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "10"});
constexpr uint16_t dataSize = UUID_INT_SIZE;
std::vector<uint8_t> guidData(UUID_INT_SIZE, 0xAB);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
guidData.data(), msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// GPU_NVLINK_PEER_TYPE=36 → Direct (peerType=0)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_GPU_NVLINK_PEER_TYPE_Direct)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "36"});
uint32_t peerType = htole32(NSM_PEER_TYPE_DIRECT);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&peerType),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// GPU_NVLINK_PEER_TYPE=36 → Bridge (peerType=1)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_GPU_NVLINK_PEER_TYPE_Bridge)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "36"});
uint32_t peerType = htole32(1); // 1 = Bridge
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&peerType),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// CHASSIS_SERIAL_NUMBER=31 (string)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_String_CHASSIS_SERIAL_NUMBER)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "31"});
const char* serial = "CHASSIS-SN-001";
uint16_t dataSize = static_cast<uint16_t>(strlen(serial));
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(
0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<const uint8_t*>(serial), msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// GPU_IBGUID=30 (uint64_t / 8 bytes)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Hex_GPU_IBGUID)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "30"});
uint64_t ibguid = 0xDEADBEEFCAFEBABEULL;
uint16_t dataSize = sizeof(uint64_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&ibguid),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// MINIMUM_EDPP_SCALING_FACTOR=24 (uint8_t)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint8_MINIMUM_EDPP_SCALING_FACTOR)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "24"});
uint8_t scalingFactor = 50;
uint16_t dataSize = sizeof(uint8_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
&scalingFactor, msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// PCIERETIMER_0_EEPROM_VERSION=144 (uint64_t, version bytes)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Version_PCIERETIMER_0_EEPROM)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "144"});
// data[0]=Major, data[2]=Minor, data[4..5]=PatchHigh, data[6]=PatchLow
uint64_t versionData = 0x0100020003000400ULL; // some version bytes
uint16_t dataSize = sizeof(uint64_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(
0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&versionData), msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: MAXIMUM_MODULE_POWER_LIMIT=18 (uncovered switch group)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MAXIMUM_MODULE_POWER_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "18"});
uint32_t value = htole32(300000);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: RATED_MODULE_POWER_LIMIT=20 (uncovered switch group)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_RATED_MODULE_POWER_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "20"});
uint32_t value = htole32(250000);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: MINIMUM_MEMORY_CLOCK_LIMIT=28
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MINIMUM_MEMORY_CLOCK_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "28"});
uint32_t value = htole32(100);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: MAXIMUM_MEMORY_CLOCK_LIMIT=29
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MAXIMUM_MEMORY_CLOCK_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "29"});
uint32_t value = htole32(1200);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: MAXIMUM_GRAPHICS_CLOCK_LIMIT=27
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MAXIMUM_GRAPHICS_CLOCK_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "27"});
uint32_t value = htole32(2000);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint32_t property: MINIMUM_GRAPHICS_CLOCK_LIMIT=26
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint32_MINIMUM_GRAPHICS_CLOCK_LIMIT)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "26"});
uint32_t value = htole32(200);
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// uint8_t property: MAXIMUM_EDPP_SCALING_FACTOR=25
TEST(NsmTelemetryCmdParse, GetInventoryInfo_Uint8_MAXIMUM_EDPP_SCALING_FACTOR)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "25"});
uint8_t scalingFactor = 100;
uint16_t dataSize = sizeof(uint8_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
&scalingFactor, msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// Error path: data size mismatch (covers lines 1140-1142)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_SizeMismatch_ErrorPath)
{
CLI::App app;
setupTelemetryCommands(app);
// MAXIMUM_MEMORY_CAPACITY=7 expects sizeof(uint32_t)=4, but we send 2
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "7"});
uint16_t wrongData = 0x1234;
uint16_t dataSize = sizeof(uint16_t); // wrong size (expected 4, got 2)
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(
0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&wrongData), msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// Unknown property (default case → cerr + return)
TEST(NsmTelemetryCmdParse, GetInventoryInfo_UnknownProperty_Default)
{
CLI::App app;
setupTelemetryCommands(app);
// property 99 is not in any switch case -> hits default
parseSubcmdArgs(app, "GetInventoryInformation", {"-p", "99"});
uint32_t value = 0;
uint16_t dataSize = sizeof(uint32_t);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_inventory_information_resp) +
dataSize);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_inventory_information_resp(0, NSM_SUCCESS, ERR_NULL, dataSize,
reinterpret_cast<uint8_t*>(&value),
msg);
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryAvailableAndClearableScalarGroup with non-zero bitfields
// -----------
// Group 2 with all bits set (covers the push_back branches)
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group2_AllBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "2"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
available[0].byte = 0x0F; // bit0..bit3 all set
clearable[0].byte = 0x0F;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// Group 3 with bit0 set (covers the L0ToRecoveryCount push_back)
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group3_AllBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "3"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
available[0].byte = 0x01; // bit0 set
clearable[0].byte = 0x01;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// Group 4 with all bits set
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group4_AllBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "4"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
available[0].byte = 0xFF; // all bits set
clearable[0].byte = 0xFF;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- GetClockOutputEnableState with NVHS and IBLINK indices -----------------
TEST(NsmTelemetryCmdParse, GetClockOutputEnableState_NVHS_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockOutputEnableState",
{"-i", "0x81"}); // NVHS_CLKBUF_INDEX
uint32_t clkBuf = 0;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_output_enabled_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_output_enable_state_resp(0, NSM_SUCCESS, ERR_NULL, clkBuf,
msg);
EXPECT_NO_THROW(commands[46]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse,
GetClockOutputEnableState_IBLINK_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockOutputEnableState",
{"-i", "0x82"}); // IBLINK_CLKBUF_INDEX
uint32_t clkBuf = 0;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_output_enabled_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_output_enable_state_resp(0, NSM_SUCCESS, ERR_NULL, clkBuf,
msg);
EXPECT_NO_THROW(commands[46]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse,
GetClockOutputEnableState_DefaultIndex_ParseResponseSuccess)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetClockOutputEnableState",
{"-i", "0x00"}); // unknown index -> default case
uint32_t clkBuf = 0;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_clock_output_enabled_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_clock_output_enable_state_resp(0, NSM_SUCCESS, ERR_NULL, clkBuf,
msg);
EXPECT_NO_THROW(commands[46]->parseResponseMsg(msg, buf.size()));
}
// ---- GetPortTelemetryCounter with all supported_counter bits set ------------
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_AllCountersSupported)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
struct nsm_port_counter_data portData{};
// Set all supported_counter bits to 1 so all if-branches are taken
memset(&portData.supported_counter, 0xFF,
sizeof(portData.supported_counter));
// Set some counter values
portData.port_rcv_pkts = 100;
portData.port_rcv_data = 200;
portData.port_xmit_pkts = 300;
portData.port_xmit_data = 400;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp) +
sizeof(nsm_port_counter_data));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_port_telemetry_counter_resp(0, NSM_SUCCESS, ERR_NULL, &portData,
msg);
EXPECT_NO_THROW(commands[0]->parseResponseMsg(msg, buf.size()));
}
// ---- Aggregate response parsing with actual samples -------------------------
// GetTemperatureReading aggregate with 1 sample (covers loop body)
TEST(NsmTelemetryCmdParse, GetTemperatureReading_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
auto buf = makeAggregateRespWithTempSample(NSM_GET_TEMPERATURE_READING, 0,
42.5);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// GetTemperatureReading aggregate with timestamp + sample (covers timestamp
// path)
TEST(NsmTelemetryCmdParse,
GetTemperatureReading_Aggregate_WithTimestampAndSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
auto buf = makeAggregateRespWithTimestampAndSample(
NSM_GET_TEMPERATURE_READING, 0, 35.0);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// GetCurrentPowerDraw aggregate with a sample (covers power reading path)
TEST(NsmTelemetryCmdParse, GetCurrentPowerDraw_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentPowerDraw", {"-s", "255"});
// Build aggregate with 1 power sample
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_POWER, NSM_SUCCESS, 1, msg);
std::array<uint8_t, 50> sampleBuf{};
auto* nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sampleBuf.data());
uint8_t reading[8]{};
size_t consumed_len{};
size_t sample_len{};
encode_aggregate_get_current_power_draw_reading(25000, reading,
&consumed_len);
encode_aggregate_resp_sample(0, true, reading, consumed_len, nsm_sample,
&sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[14]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- Helper: append a sample to an aggregate response buffer ---------------
static void appendAggSample(std::vector<uint8_t>& buf, uint8_t tag,
const uint8_t* data, size_t data_len)
{
std::array<uint8_t, 64> sampleBuf{};
auto* nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sampleBuf.data());
size_t sample_len{};
encode_aggregate_resp_sample(tag, true, data, data_len, nsm_sample,
&sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
}
// ---- QueryAvailableAndClearableScalarGroup GROUP_ID_8 ----------------------
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group8_AllBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "8"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
available[0].byte = 0xFF;
clearable[0].byte = 0xFF;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryAvailableAndClearableScalarGroup GROUP_ID_9 ----------------------
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_Group9_AllBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "9"});
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
available[0].byte = 0xFF;
clearable[0].byte = 0xFF;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryAvailableAndClearableScalarGroup default (unknown groupId) --------
TEST(NsmTelemetryCmdParse, QueryAvailableAndClearableScalarGroup_DefaultGroupId)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", "99"});
// default branch just prints error; no decode called
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_available_clearable_scalar_data_sources_v1_resp) + 1);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
bitfield8_t available[1]{};
bitfield8_t clearable[1]{};
encode_query_available_clearable_scalar_data_sources_v1_resp(
0, NSM_SUCCESS, ERR_NULL,
static_cast<uint16_t>(sizeof(uint8_t) + 2 * sizeof(uint8_t)), 1,
reinterpret_cast<uint8_t*>(available),
reinterpret_cast<uint8_t*>(clearable), msg);
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
// ---- GetPowerSmoothingFeatureInfoV2 with all sample tags -------------------
TEST(NsmTelemetryCmdParse, GetPowerSmoothingFeatureInfoV2_AllSampleTags)
{
CLI::App app;
setupTelemetryCommands(app);
// 8 samples: FEATURE_FLAG_TAG..MIN_PRIMARY_FLOOR_ACTIVATION_POINT_TAG
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 8, msg);
uint8_t d[8]{};
size_t dl{};
encodeFeatureFlagSample(0x0F, d, &dl);
appendAggSample(buf, FEATURE_FLAG_TAG, d, dl);
encodeCurrentTMPSettingSample(100, d, &dl);
appendAggSample(buf, CURRENT_TMP_SETTING_TAG, d, dl);
encodeCurrentTMPFloorSettingSample(200, d, &dl);
appendAggSample(buf, TMP_FLOOR_SETTING_TAG, d, dl);
encodeMaxTmpFloorSettingSample(300, d, &dl);
appendAggSample(buf, MAX_TMP_FLOOR_SETTING_TAG, d, dl);
encodeMinTmpFloorSettingSample(50, d, &dl);
appendAggSample(buf, MIN_TMP_FLOOR_SETTING_TAG, d, dl);
encodeFloorWindowMultiplierSample(5, d, &dl);
appendAggSample(buf, FLOOR_WINDOW_MULTIPLIER_TAG, d, dl);
encodeMinPrimaryFloorActivationOffset(10, d, &dl);
appendAggSample(buf, MIN_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, d, dl);
encodeMinPrimaryFloorActivationPoint(20, d, &dl);
appendAggSample(buf, MIN_PRIMARY_FLOOR_ACTIVATION_POINT_TAG, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[59]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingCurrentProfileInformationV2 with all tags ------------
TEST(NsmTelemetryCmdParse, GetPowerSmoothingCurrentProfileInfoV2_AllSampleTags)
{
CLI::App app;
setupTelemetryCommands(app);
// 10 tags:
// ACTIVE_PRESET_PROFILE_ID_TAG..CURRENT_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 10, msg);
uint8_t d[8]{};
size_t dl{};
encodeActivePresetProfileSample(1, d, &dl);
appendAggSample(buf, ACTIVE_PRESET_PROFILE_ID_TAG, d, dl);
encodeAdminOverrideMaskSample(0xFF, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_MASK_TAG, d, dl);
encodeCurrentTMPFloorSample(200, d, &dl);
appendAggSample(buf, CURRENT_TMP_FLOOR_SETTING_TAG, d, dl);
encodeCurrentRampupRateSample(300, d, &dl);
appendAggSample(buf, CURRENT_RAMPUP_RATE_TAG, d, dl);
encodeCurrentRampdownRateSample(400, d, &dl);
appendAggSample(buf, CURRENT_RAMPDOWN_RATE_TAG, d, dl);
encodeCurrentRampdownHysteresisSample(500, d, &dl);
appendAggSample(buf, CURRENT_RAMPDOWN_HYSTERESIS_TAG, d, dl);
encodeCurrentSecondaryFloorSample(600, d, &dl);
appendAggSample(buf, CURRENT_SECONDARY_FLOOR_TAG, d, dl);
encodeCurrentPrimaryFloorActivationWindowMultiplierSample(7, d, &dl);
appendAggSample(buf, CURRENT_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG,
d, dl);
encodeCurrentPrimaryFloorTargetWindowSample(8, d, &dl);
appendAggSample(buf, CURRENT_PRIMARY_FLOOR_TARGET_WINDOW_TAG, d, dl);
encodeCurrentPrimaryFloorActivationOffsetSample(9000, d, &dl);
appendAggSample(buf, CURRENT_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[60]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingAdminOverrideProfileInformationV2 with all tags ------
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingAdminOverrideProfileInfoV2_AllSampleTags)
{
CLI::App app;
setupTelemetryCommands(app);
// 8 samples: ADMIN_OVERRIDE_PROFILE_TMP_FLOOR_SETTING_TAG..
// ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 8, msg);
uint8_t d[8]{};
size_t dl{};
encodeCurrentTMPFloorSample(100, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_TMP_FLOOR_SETTING_TAG, d, dl);
encodeCurrentRampupRateSample(200, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_RAMPUP_RATE_TAG, d, dl);
encodeCurrentRampdownRateSample(300, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_RAMPDOWN_RATE_TAG, d, dl);
encodeCurrentRampdownHysteresisSample(400, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_RAMPDOWN_HYSTERESIS_TAG, d, dl);
encodeCurrentSecondaryFloorSample(500, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_SECONDARY_FLOOR_TAG, d, dl);
encodeCurrentPrimaryFloorActivationWindowMultiplierSample(6, d, &dl);
appendAggSample(
buf,
ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG,
d, dl);
encodeCurrentPrimaryFloorTargetWindowSample(7, d, &dl);
appendAggSample(buf, ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_TARGET_WINDOW_TAG,
d, dl);
encodeCurrentPrimaryFloorActivationOffsetSample(8000, d, &dl);
appendAggSample(
buf, ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[61]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingPresetProfileInformationV2 with all profile tags -----
TEST(NsmTelemetryCmdParse, GetPowerSmoothingPresetProfileInfoV2_AllSampleTags)
{
CLI::App app;
setupTelemetryCommands(app);
// Preset profile tag = (tagId << 3) | profId; use profId=0 for all
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 8, msg);
uint8_t d[8]{};
size_t dl{};
// PRESET_PROFILE_TMP_FLOOR_SETTING_TAG=0: tag=(0<<3)|0=0
encodeCurrentTMPFloorSample(100, d, &dl);
appendAggSample(
buf, static_cast<uint8_t>(PRESET_PROFILE_TMP_FLOOR_SETTING_TAG << 3), d,
dl);
// PRESET_PROFILE_RAMPUP_RATE_TAG=1: tag=(1<<3)|0=8
encodeCurrentRampupRateSample(200, d, &dl);
appendAggSample(
buf, static_cast<uint8_t>(PRESET_PROFILE_RAMPUP_RATE_TAG << 3), d, dl);
// PRESET_PROFILE_RAMPDOWN_RATE_TAG=2: tag=(2<<3)|0=16
encodeCurrentRampdownRateSample(300, d, &dl);
appendAggSample(buf,
static_cast<uint8_t>(PRESET_PROFILE_RAMPDOWN_RATE_TAG << 3),
d, dl);
// PRESET_PROFILE_RAMPDOWN_HYSTERESIS_TAG=3: tag=(3<<3)|0=24
encodeCurrentRampdownHysteresisSample(400, d, &dl);
appendAggSample(
buf, static_cast<uint8_t>(PRESET_PROFILE_RAMPDOWN_HYSTERESIS_TAG << 3),
d, dl);
// PRESET_PROFILE_SECONDARY_FLOOR_TAG=4: tag=(4<<3)|0=32
encodeCurrentSecondaryFloorSample(500, d, &dl);
appendAggSample(
buf, static_cast<uint8_t>(PRESET_PROFILE_SECONDARY_FLOOR_TAG << 3), d,
dl);
// PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG=5:
// tag=(5<<3)|0=40
encodeCurrentPrimaryFloorActivationWindowMultiplierSample(6, d, &dl);
appendAggSample(
buf,
static_cast<uint8_t>(
PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG << 3),
d, dl);
// PRESET_PROFILE_PRIMARY_FLOOR_TARGET_WINDOW_TAG=6: tag=(6<<3)|0=48
encodeCurrentPrimaryFloorTargetWindowSample(7, d, &dl);
appendAggSample(buf,
static_cast<uint8_t>(
PRESET_PROFILE_PRIMARY_FLOOR_TARGET_WINDOW_TAG << 3),
d, dl);
// PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG=7: tag=(7<<3)|0=56
encodeCurrentPrimaryFloorActivationOffsetSample(8000, d, &dl);
appendAggSample(
buf,
static_cast<uint8_t>(PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG
<< 3),
d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[62]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetEthPortTelemetryCounter with a counter data sample -----------------
TEST(NsmTelemetryCmdParse, GetEthPortTelemetryCounter_WithCounterSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetEthPortTelemetryCounter", {"-p", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
nsm_ethernet_port_counter_data counter{};
counter.ethernet_port_counter_data_64bit = 12345;
uint8_t d[8]{};
size_t dl = sizeof(d); // must pre-set to buffer capacity
encode_aggregate_eth_port_telemetry_data(0, &counter, d, &dl);
appendAggSample(buf, 0, d, dl); // tag=0 -> RXBytes (64-bit)
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[56]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPortNetworkAddresses with a link-type sample -----------------------
TEST(NsmTelemetryCmdParse, GetPortNetworkAddresses_WithLinkTypeSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortNetworkAddresses", {"-p", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
network_address_sample_data address{};
address.link_type = 1;
uint8_t d[16]{};
size_t dl{};
encode_aggregate_network_address_data(NSM_TAG_LINK_TYPE, &address, d, &dl);
appendAggSample(buf, NSM_TAG_LINK_TYPE, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[57]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPortEccCounters with an ECC counter sample -------------------------
TEST(NsmTelemetryCmdParse, GetPortEccCounters_WithEccCounterSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortEccCounters", {"-p", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_port_ecc_counter_data(NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES,
999, d, &dl);
appendAggSample(buf, NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[58]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- Error paths: all simple commands (payloadLength=0 → decode fails) -----
TEST(NsmTelemetryCmdParse, ErrorPaths_Commands0to11)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
// All pass payloadLength=0 to trigger decode_*_resp failure
EXPECT_NO_THROW(
commands[0]->parseResponseMsg(msg, 0)); // GetPortTelemetryCounter
EXPECT_NO_THROW(
commands[1]->parseResponseMsg(msg, 0)); // QueryPortCharacteristics
EXPECT_NO_THROW(commands[2]->parseResponseMsg(msg, 0)); // QueryPortStatus
EXPECT_NO_THROW(
commands[3]->parseResponseMsg(msg, 0)); // QueryPortsAvailable
EXPECT_NO_THROW(
commands[4]->parseResponseMsg(msg, 0)); // SetPortDisableFuture
EXPECT_NO_THROW(
commands[5]->parseResponseMsg(msg, 0)); // GetFabricManagerState
EXPECT_NO_THROW(
commands[6]->parseResponseMsg(msg, 0)); // GetPortDisableFuture
EXPECT_NO_THROW(commands[7]->parseResponseMsg(msg, 0)); // GetPowerMode
EXPECT_NO_THROW(commands[8]->parseResponseMsg(msg, 0)); // SetPowerMode
EXPECT_NO_THROW(
commands[9]->parseResponseMsg(msg, 0)); // GetSwitchIsolationMode
EXPECT_NO_THROW(
commands[10]->parseResponseMsg(msg, 0)); // SetSwitchIsolationMode
EXPECT_NO_THROW(
commands[11]->parseResponseMsg(msg, 0)); // GetInventoryInformation
}
// ---- Error paths: aggregate commands (payloadLength=0 → decode_aggregate_resp
// fails → hits AggregateResponseParser error path at lines 1344-1347) ---
TEST(NsmTelemetryCmdParse, DISABLED_ErrorPaths_AggregateCommands12to17)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
// payloadLength=0 → msg_len=sizeof(nsm_msg_hdr)=8 < 12 needed
// → decode_aggregate_resp fails → AggregateResponseParser error path
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, 0)); // GetTemperatureReading
EXPECT_NO_THROW(
commands[14]->parseResponseMsg(msg, 0)); // GetCurrentPowerDraw
EXPECT_NO_THROW(
commands[15]->parseResponseMsg(msg, 0)); // GetMaxObservedPower
EXPECT_NO_THROW(
commands[16]->parseResponseMsg(msg, 0)); // GetCurrentEnergyCount
EXPECT_NO_THROW(commands[17]->parseResponseMsg(msg, 0)); // GetVoltage
}
TEST(NsmTelemetryCmdParse, DISABLED_ErrorPaths_Commands13_18to30)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(
commands[13]->parseResponseMsg(msg, 0)); // ReadThermalParameter
EXPECT_NO_THROW(
commands[18]->parseResponseMsg(msg, 0)); // GetAltitudePressure
EXPECT_NO_THROW(commands[19]->parseResponseMsg(msg, 0)); // GetDriverInfo
EXPECT_NO_THROW(commands[20]->parseResponseMsg(msg, 0)); // GetMigMode
EXPECT_NO_THROW(commands[21]->parseResponseMsg(msg, 0)); // SetMigMode
EXPECT_NO_THROW(commands[22]->parseResponseMsg(msg, 0)); // GetEccMode
EXPECT_NO_THROW(commands[23]->parseResponseMsg(msg, 0)); // SetEccMode
EXPECT_NO_THROW(
commands[24]->parseResponseMsg(msg, 0)); // GetEccErrorCounts
EXPECT_NO_THROW(commands[25]->parseResponseMsg(msg, 0)); // SetClockLimit
EXPECT_NO_THROW(
commands[26]->parseResponseMsg(msg, 0)); // GetEDPpScalingFactors
EXPECT_NO_THROW(
commands[27]->parseResponseMsg(msg, 0)); // SetEDPpScalingFactors
EXPECT_NO_THROW(
commands[28]->parseResponseMsg(msg, 0)); // QueryScalarGroupTelemetry
EXPECT_NO_THROW(
commands[31]->parseResponseMsg(msg, 0)); // PcieFundamentalReset
}
TEST(NsmTelemetryCmdParse, DISABLED_ErrorPaths_Commands31to53)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(
commands[32]->parseResponseMsg(msg, 0)); // ClearScalarDataSource
EXPECT_NO_THROW(commands[33]->parseResponseMsg(msg, 0)); // GetClockLimit
EXPECT_NO_THROW(commands[34]->parseResponseMsg(msg, 0)); // SetPowerLimit
EXPECT_NO_THROW(commands[35]->parseResponseMsg(msg, 0)); // GetPowerLimit
EXPECT_NO_THROW(commands[36]->parseResponseMsg(msg, 0)); // GetCurrClockFreq
EXPECT_NO_THROW(
commands[37]->parseResponseMsg(msg, 0)); // GetAccumGpuUtilTime
EXPECT_NO_THROW(
commands[38]->parseResponseMsg(msg, 0)); // GetProcessorThrottleReason
EXPECT_NO_THROW(commands[39]->parseResponseMsg(msg, 0)); // GetRowRemapState
EXPECT_NO_THROW(
commands[40]->parseResponseMsg(msg, 0)); // GetRowRemappingCounts
EXPECT_NO_THROW(
commands[41]->parseResponseMsg(msg, 0)); // GetRowRemapAvailability
EXPECT_NO_THROW(
commands[42]->parseResponseMsg(msg, 0)); // GetLeakDetectionInfo
EXPECT_NO_THROW(
commands[43]->parseResponseMsg(msg, 0)); // SetLeakDetectionThresholds
EXPECT_NO_THROW(
commands[44]->parseResponseMsg(msg, 0)); // GetMemoryCapacityUtil
EXPECT_NO_THROW(
commands[45]->parseResponseMsg(msg, 0)); // GetCurrentUtilization
EXPECT_NO_THROW(
commands[46]->parseResponseMsg(msg, 0)); // GetClockOutputEnableState
EXPECT_NO_THROW(
commands[47]->parseResponseMsg(msg, 0)); // GetSupportedGPMMetrics
EXPECT_NO_THROW(commands[48]->parseResponseMsg(
msg, 0)); // QueryAggregatedGPMMetrics (aggregate)
EXPECT_NO_THROW(commands[49]->parseResponseMsg(
msg, 0)); // QueryPerInstanceGPMMetrics (aggregate)
EXPECT_NO_THROW(commands[50]->parseResponseMsg(
msg, 0)); // QueryPerInstanceGPMMetricsV2 (aggregate)
EXPECT_NO_THROW(
commands[51]->parseResponseMsg(msg, 0)); // GetViolationDuration
EXPECT_NO_THROW(
commands[52]->parseResponseMsg(msg, 0)); // GetListAvailablePciePorts
EXPECT_NO_THROW(commands[53]->parseResponseMsg(
msg, 0)); // GetPCIePortConfig (aggregate)
EXPECT_NO_THROW(
commands[54]->parseResponseMsg(msg, 0)); // SetPCIePortConfig
EXPECT_NO_THROW(commands[55]->parseResponseMsg(
msg, 0)); // QueryMultiportScalarGroupTelemetry
}
// ---- Error paths: commands 55-61 aggregate handlers ----------------------
TEST(NsmTelemetryCmdParse, DISABLED_ErrorPaths_Commands55to61_Aggregate)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(
commands[56]->parseResponseMsg(msg, 0)); // GetEthPortTelemetryCounter
EXPECT_NO_THROW(
commands[57]->parseResponseMsg(msg, 0)); // GetPortNetworkAddresses
EXPECT_NO_THROW(
commands[58]->parseResponseMsg(msg, 0)); // GetPortEccCounters
EXPECT_NO_THROW(commands[59]->parseResponseMsg(
msg, 0)); // GetPowerSmoothingFeatureInfoV2
EXPECT_NO_THROW(commands[60]->parseResponseMsg(
msg, 0)); // GetPowerSmoothingCurrentProfileInfoV2
EXPECT_NO_THROW(commands[61]->parseResponseMsg(
msg, 0)); // GetPowerSmoothingAdminOverrideV2
EXPECT_NO_THROW(commands[62]->parseResponseMsg(
msg, 0)); // GetPowerSmoothingPresetProfileInfoV2
}
// ---- Error paths: QueryAvailableAndClearableScalarGroup for each groupId --
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_ErrorPath_AllGroupIds)
{
CLI::App app;
setupTelemetryCommands(app);
// Pass payloadLength=0 with each groupId set → decode fails → error path
for (int gid : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99})
{
parseSubcmdArgs(app, "QueryAvailableAndClearableScalarGroup",
{"-d", "0", "-g", std::to_string(gid)});
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN,
0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, 0));
}
}
// ---- GetListAvailablePciePorts with 1 port (covers the ports loop) ---------
TEST(NsmTelemetryCmdParse, GetListAvailablePciePorts_WithOnePciPort)
{
CLI::App app;
setupTelemetryCommands(app);
// Build info with 1 upstream port
std::vector<uint8_t> infoBuf(sizeof(nsm_list_available_pcie_ports_info) +
sizeof(nsm_pcie_upstream_port_info));
auto* info =
reinterpret_cast<nsm_list_available_pcie_ports_info*>(infoBuf.data());
info->ports_count = 1;
info->ports[0].type = NSM_PORT_TYPE_UPSTREAM;
info->ports[0].downstream_ports_count = 2;
std::vector<uint8_t> buf(NSM_LIST_AVAILABLE_PCIE_PORTS_RESPONSE_MIN_LEN);
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_list_available_pcie_ports_resp(0, NSM_SUCCESS, ERR_NULL, info, msg);
EXPECT_NO_THROW(commands[52]->parseResponseMsg(msg, buf.size()));
}
// ---- GetLeakDetectionInfo with 1 sensor (covers sensor-loop in parseResponse)
TEST(NsmTelemetryCmdParse, GetLeakDetectionInfo_WithOneSensor)
{
CLI::App app;
setupTelemetryCommands(app);
uint8_t numSensors = 1;
uint8_t numThresholdLevels = 1;
// Sensor data: sensor_id, leak_state, adc_reading(2 bytes), threshold(2
// bytes)
struct
{
uint8_t sensor_id;
uint8_t leak_state;
uint16_t adc_reading;
uint16_t thresholds[1];
} __attribute__((packed)) sensorData{};
sensorData.sensor_id = 0;
sensorData.leak_state = 0;
sensorData.adc_reading = 100;
sensorData.thresholds[0] = 200;
std::vector<uint8_t> sensorsBuf(sizeof(sensorData));
std::memcpy(sensorsBuf.data(), &sensorData, sizeof(sensorData));
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_leak_detection_info_resp) +
sizeof(sensorData));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_leak_detection_info_resp(0, NSM_SUCCESS, ERR_NULL, numSensors,
numThresholdLevels, sensorsBuf.data(),
sensorsBuf.size(), msg);
EXPECT_NO_THROW(commands[42]->parseResponseMsg(msg, buf.size()));
}
// ---- GetEthPortTelemetryCounter: 32-bit tags (tags 8-20) -------------------
TEST(NsmTelemetryCmdParse, GetEthPortTelemetryCounter_32BitTags)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetEthPortTelemetryCounter", {"-p", "0"});
// Test tags 8-20 (32-bit counters)
for (uint8_t tag = 8; tag <= 20; ++tag)
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
nsm_ethernet_port_counter_data counter{};
counter.ethernet_port_counter_data_32bit = 42;
uint8_t d[4]{};
size_t dl = sizeof(d); // 4 bytes for 32-bit tags
encode_aggregate_eth_port_telemetry_data(tag, &counter, d, &dl);
appendAggSample(buf, tag, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[56]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// ---- GetEthPortTelemetryCounter: 64-bit tags 1-7 ---------------------------
TEST(NsmTelemetryCmdParse, GetEthPortTelemetryCounter_64BitTags1to7)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetEthPortTelemetryCounter", {"-p", "0"});
// Test tags 1-7 (also 64-bit counters)
for (uint8_t tag = 1; tag <= 7; ++tag)
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
nsm_ethernet_port_counter_data counter{};
counter.ethernet_port_counter_data_64bit = 999;
uint8_t d[8]{};
size_t dl = sizeof(d); // 8 bytes for 64-bit tags
encode_aggregate_eth_port_telemetry_data(tag, &counter, d, &dl);
appendAggSample(buf, tag, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[56]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// ---- GetPortNetworkAddresses: remaining tags (MAC, PERMANENT_MAC, GUID) ----
TEST(NsmTelemetryCmdParse, GetPortNetworkAddresses_MacAddressTags)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortNetworkAddresses", {"-p", "0"});
// Test NSM_TAG_MAC_ADDRESS and NSM_TAG_PERMANENT_MAC_ADDRESS
for (uint8_t tag :
{(uint8_t)NSM_TAG_MAC_ADDRESS, (uint8_t)NSM_TAG_PERMANENT_MAC_ADDRESS})
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
network_address_sample_data address{};
// mac_address[8] filled with test data
for (int i = 0; i < MAC_ADDRESS_LENGTH; ++i)
address.mac_address[i] = static_cast<uint8_t>(i + 1);
uint8_t d[MAC_ADDRESS_LENGTH]{};
size_t dl{};
encode_aggregate_network_address_data(tag, &address, d, &dl);
appendAggSample(buf, tag, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[57]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
TEST(NsmTelemetryCmdParse, GetPortNetworkAddresses_GuidTags)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortNetworkAddresses", {"-p", "0"});
// Test NSM_TAG_NODE_GUID and NSM_TAG_PORT_GUID
for (uint8_t tag : {(uint8_t)NSM_TAG_NODE_GUID, (uint8_t)NSM_TAG_PORT_GUID})
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
network_address_sample_data address{};
address.network_identifier_64bit = 0xDEADBEEFCAFE1234ULL;
uint8_t d[8]{};
size_t dl{};
encode_aggregate_network_address_data(tag, &address, d, &dl);
appendAggSample(buf, tag, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[57]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// ---- GetPortEccCounters: all remaining tags (1-5) --------------------------
TEST(NsmTelemetryCmdParse, GetPortEccCounters_AllRemainingTags)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortEccCounters", {"-p", "0"});
for (uint8_t tag = NSM_TAG_ECC_CORRECTED_BITS;
tag <= NSM_TAG_ECC_RAW_ERRORS_LANE_3; ++tag)
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_port_ecc_counter_data(tag, 42, d, &dl);
appendAggSample(buf, tag, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[58]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// ---- Aggregate-with-sample for commands 13,15,16,17 -----------------------
TEST(NsmTelemetryCmdParse, ReadThermalParameter_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "ReadThermalParameter", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_READ_THERMAL_PARAMETER, NSM_SUCCESS, 1, msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_thermal_parameter_data(-50, d, &dl);
appendAggSample(buf, 0, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[13]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
TEST(NsmTelemetryCmdParse, GetMaxObservedPower_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetMaxObservedPower", {"-s", "255", "-a", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_MAX_OBSERVED_POWER, NSM_SUCCESS, 1, msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_get_current_power_draw_reading(75000, d, &dl);
appendAggSample(buf, 0, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[15]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
TEST(NsmTelemetryCmdParse, GetCurrentEnergyCount_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetCurrentEnergyCount", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_ENERGY_COUNT, NSM_SUCCESS, 1, msg);
uint8_t d[16]{};
size_t dl{};
encode_aggregate_energy_count_data(123456789ULL, d, &dl);
appendAggSample(buf, 0, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[16]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
TEST(NsmTelemetryCmdParse, GetVoltage_Aggregate_WithSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetVoltage", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_VOLTAGE, NSM_SUCCESS, 1, msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_voltage_data(1000, d, &dl);
appendAggSample(buf, 0, d, dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[17]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- QueryScalarGroupTelemetry: error path for each groupId ----------------
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_AllGroups_ErrorPaths)
{
for (int g : {0, 1, 2, 3, 4, 5, 6, 8, 9, 10})
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry",
{"-d", "0", "-g", std::to_string(g)});
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN,
0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, 0));
}
}
// ---- GetProcessorThrottleReason: all 6 throttle flag bits ------------------
TEST(NsmTelemetryCmdParse, GetProcessorThrottleReason_AllFlagsSet)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield32_t flags{};
flags.byte = 0x3F; // bits 0-5 all set
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_clock_event_reason_code_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_current_clock_event_reason_code_resp(0, NSM_SUCCESS, ERR_NULL,
&flags, msg);
EXPECT_NO_THROW(commands[38]->parseResponseMsg(msg, buf.size()));
}
// ---- AggregateResponseParser error paths -----------------------------------
// !valid sample → triggers lines 1379-1383
TEST(NsmTelemetryCmdParse, AggregateParser_InvalidSample_Skips)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_TEMPERATURE_READING, NSM_SUCCESS, 1, msg);
// Encode sample with valid=false to trigger !valid check
uint8_t d[8]{};
size_t dl{};
encode_aggregate_temperature_reading_data(20.0, d, &dl);
std::array<uint8_t, 64> sampleBuf{};
auto* nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sampleBuf.data());
size_t sample_len{};
encode_aggregate_resp_sample(0, false, d, dl, nsm_sample, &sample_len);
buf.insert(buf.end(), sampleBuf.begin(),
std::next(sampleBuf.begin(), sample_len));
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// Timestamp with data_len != 8 → triggers lines 1390-1395
TEST(NsmTelemetryCmdParse, AggregateParser_TimestampWrongSize_Skips)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_TEMPERATURE_READING, NSM_SUCCESS, 1, msg);
// tag=0xFF with 4-byte data (not 8) → triggers wrong-size timestamp error
uint8_t d[4]{};
appendAggSample(buf, 0xFF, d, 4);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// handleSampleData returns non-success → triggers lines 1423-1428
TEST(NsmTelemetryCmdParse, AggregateParser_HandleSampleDataFails_Skips)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetTemperatureReading", {"-s", "255"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_GET_TEMPERATURE_READING, NSM_SUCCESS, 1, msg);
// 4-byte temperature sample (decode_aggregate_temperature_reading_data
// expects 8 bytes for double) → decode fails, handleSampleData returns err
uint8_t d[4]{};
appendAggSample(buf, 0, d, 4);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[12]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- QueryAggregatedGPMMetrics: PERCENTAGE and BANDWIDTH sample paths ------
TEST(NsmTelemetryCmdParse, QueryAggregatedGPMMetrics_PercentageSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAggregatedGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_QUERY_AGGREGATE_GPM_METRICS, NSM_SUCCESS, 1,
msg);
uint8_t d[8]{};
size_t dl{};
encode_aggregate_gpm_metric_percentage_data(75.0, d, &dl);
appendAggSample(buf, 0, d, dl); // tag=0 = GraphicsEngineActivityPercent
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[48]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
TEST(NsmTelemetryCmdParse, QueryAggregatedGPMMetrics_BandwidthSample)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAggregatedGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_QUERY_AGGREGATE_GPM_METRICS, NSM_SUCCESS, 1,
msg);
uint8_t d[16]{};
size_t dl{};
encode_aggregate_gpm_metric_bandwidth_data(1024ULL * 1024 * 128, d, &dl);
appendAggSample(buf, 8, d, dl); // tag=8 = PCIeRawTxBandwidthGbps
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[48]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// tag not in metricsTable → lines 4661-4664 (returns NSM_SW_ERROR_DATA)
TEST(NsmTelemetryCmdParse, QueryAggregatedGPMMetrics_UnknownTagError)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryAggregatedGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, NSM_QUERY_AGGREGATE_GPM_METRICS, NSM_SUCCESS, 1,
msg);
uint8_t d[4]{};
appendAggSample(buf, 32, d, 4); // tag=32 not in metricsTable (0-31)
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[48]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// metricId not in metricsTable → early return at lines 4844-4845
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetrics_UnknownMetricId)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPerInstanceGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-i", "255", "-b", "1"});
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(commands[49]->parseResponseMsg(msg, 0));
}
// metricId not in metricsTable → early return at lines 4913-4914
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetricsV2_UnknownMetricId)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryPerInstanceGPMMetricsV2",
{"-r", "0", "-g", "0", "-c", "0", "-i", "255", "-b", "1"});
std::vector<uint8_t> hdr(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN, 0);
auto* msg = reinterpret_cast<nsm_msg*>(hdr.data());
EXPECT_NO_THROW(commands[50]->parseResponseMsg(msg, 0));
}
// ---- GetPowerSmoothingFeatureInfoV2: handleSampleData error paths ----------
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingFeatureInfoV2_HandleSampleDataErrors)
{
// Each tag with wrong data_len triggers decode failure → lines 5143..5235
// Expected sizes: uint32 tags=4, uint16 tags=2; pass 8 or 4 respectively
const std::vector<std::pair<uint8_t, size_t>> tag_dl = {
{FEATURE_FLAG_TAG, 8}, // expects 4
{CURRENT_TMP_SETTING_TAG, 8}, // expects 4
{TMP_FLOOR_SETTING_TAG, 8}, // expects 4
{MAX_TMP_FLOOR_SETTING_TAG, 4}, // expects 2
{MIN_TMP_FLOOR_SETTING_TAG, 4}, // expects 2
{FLOOR_WINDOW_MULTIPLIER_TAG, 8}, // expects 4
{MIN_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, 8}, // expects 4
{MIN_PRIMARY_FLOOR_ACTIVATION_POINT_TAG, 8}, // expects 4
};
for (auto& [tag, dl] : tag_dl)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
std::vector<uint8_t> d(dl, 0);
appendAggSample(buf, tag, d.data(), dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[59]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// Unknown tag in FeatureInfoV2 → else branch lines 5241-5243
TEST(NsmTelemetryCmdParse, GetPowerSmoothingFeatureInfoV2_UnknownTagError)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[4]{};
appendAggSample(buf, 9, d, 4); // tag=9 not in switch
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[59]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingCurrentProfileInfoV2: handleSampleData errors --------
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingCurrentProfileInfoV2_HandleSampleDataErrors)
{
// tag → wrong dl to trigger decode failure
const std::vector<std::pair<uint8_t, size_t>> tag_dl = {
{ACTIVE_PRESET_PROFILE_ID_TAG, 2}, // 1
{ADMIN_OVERRIDE_MASK_TAG, 4}, // 2
{CURRENT_TMP_FLOOR_SETTING_TAG, 4}, // 2
{CURRENT_RAMPUP_RATE_TAG, 8}, // 4
{CURRENT_RAMPDOWN_RATE_TAG, 8}, // 4
{CURRENT_RAMPDOWN_HYSTERESIS_TAG, 8}, // 4
{CURRENT_SECONDARY_FLOOR_TAG, 8}, // 4
{CURRENT_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG, 2}, // 1
{CURRENT_PRIMARY_FLOOR_TARGET_WINDOW_TAG, 2}, // 1
{CURRENT_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, 8}, // 4
};
for (auto& [tag, dl] : tag_dl)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
std::vector<uint8_t> d(dl, 0);
appendAggSample(buf, tag, d.data(), dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[60]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// Unknown tag in CurrentProfileInfoV2 → else branch lines 5461-5463
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingCurrentProfileInfoV2_UnknownTagError)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[4]{};
appendAggSample(buf, 10, d, 4); // tag=10 not in switch
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[60]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingAdminOverrideProfileInfoV2: handleSampleData errors --
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingAdminOverrideProfileInfoV2_HandleSampleDataErrors)
{
const std::vector<std::pair<uint8_t, size_t>> tag_dl = {
{ADMIN_OVERRIDE_PROFILE_TMP_FLOOR_SETTING_TAG, 4}, // 2
{ADMIN_OVERRIDE_PROFILE_RAMPUP_RATE_TAG, 8}, // 4
{ADMIN_OVERRIDE_PROFILE_RAMPDOWN_RATE_TAG, 8}, // 4
{ADMIN_OVERRIDE_PROFILE_RAMPDOWN_HYSTERESIS_TAG, 8}, // 4
{ADMIN_OVERRIDE_PROFILE_SECONDARY_FLOOR_TAG, 8}, // 4
{ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG,
2}, // 1
{ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_TARGET_WINDOW_TAG, 2}, // 1
{ADMIN_OVERRIDE_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG, 8}, // 4
};
for (auto& [tag, dl] : tag_dl)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
std::vector<uint8_t> d(dl, 0);
appendAggSample(buf, tag, d.data(), dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[61]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// Unknown tag in AdminOverrideProfileInfoV2 → else branch lines 5801-5803
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingAdminOverrideProfileInfoV2_UnknownTagError)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[4]{};
appendAggSample(buf, 8, d, 4); // tag=8 not in switch
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[61]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPowerSmoothingPresetProfileInfoV2: handleSampleData error paths ----
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingPresetProfileInfoV2_HandleSampleDataErrors)
{
// Preset tag = (tagId << 3) | profId; wrong dl to trigger decode failure
// tagId 0-7 map to tags 0,8,16,24,32,40,48,56 (profId=0)
const std::vector<std::pair<uint8_t, size_t>> tag_dl = {
{static_cast<uint8_t>(PRESET_PROFILE_TMP_FLOOR_SETTING_TAG << 3),
4}, // tagId=0 → tag=0, expects 2
{static_cast<uint8_t>(PRESET_PROFILE_RAMPUP_RATE_TAG << 3),
8}, // tagId=1 → tag=8, expects 4
{static_cast<uint8_t>(PRESET_PROFILE_RAMPDOWN_RATE_TAG << 3),
8}, // tagId=2 → tag=16, expects 4
{static_cast<uint8_t>(PRESET_PROFILE_RAMPDOWN_HYSTERESIS_TAG << 3),
8}, // tagId=3 → tag=24, expects 4
{static_cast<uint8_t>(PRESET_PROFILE_SECONDARY_FLOOR_TAG << 3),
8}, // tagId=4 → tag=32, expects 4
{static_cast<uint8_t>(
PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_WINDOW_MULTIPLIER_TAG
<< 3),
2}, // tagId=5 → tag=40, expects 1
{static_cast<uint8_t>(PRESET_PROFILE_PRIMARY_FLOOR_TARGET_WINDOW_TAG
<< 3),
2}, // tagId=6 → tag=48, expects 1
{static_cast<uint8_t>(PRESET_PROFILE_PRIMARY_FLOOR_ACTIVATION_OFFSET_TAG
<< 3),
8}, // tagId=7 → tag=56, expects 4
};
for (auto& [tag, dl] : tag_dl)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
std::vector<uint8_t> d(dl, 0);
appendAggSample(buf, tag, d.data(), dl);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[62]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// Unknown tagId in PresetProfileInfoV2 → else branch lines 5635-5637
TEST(NsmTelemetryCmdParse, GetPowerSmoothingPresetProfileInfoV2_UnknownTagError)
{
CLI::App app;
setupTelemetryCommands(app);
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
// tagId=8 → tag=(8<<3)|0=64, not in switch
uint8_t d[4]{};
appendAggSample(buf, 64, d, 4);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[62]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetMigMode: MigModeEnabled=true branch (line 2124) --------------------
TEST(NsmTelemetryCmdParse, GetMigMode_FlagBit0Set)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
flags.bits.bit0 = 1; // MigModeEnabled = true
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_MIG_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_MIG_mode_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[20]->parseResponseMsg(msg, buf.size()));
}
// ---- GetEccMode: ECCModeEnabled=true and PendingECCState=true (2239,2247) --
TEST(NsmTelemetryCmdParse, GetEccMode_AllFlagsSet)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
flags.byte = 0x03; // bit0=1 (ECCModeEnabled), bit1=1 (PendingECCState)
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_ECC_mode_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_ECC_mode_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[22]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryPerInstanceGPMMetrics: valid metricId PERCENTAGE (4844-4845,
// 4748-4783) ----
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetrics_ValidMetricId_Percentage)
{
CLI::App app;
setupTelemetryCommands(app);
// metricId=0 is GPMMetricsUnit::PERCENTAGE
parseSubcmdArgs(app, "QueryPerInstanceGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-i", "0", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
// decode_aggregate_gpm_metric_percentage_data expects 4 bytes (uint32_t)
uint32_t pct_data = htole32(static_cast<uint32_t>(50.0 * 256)); // 50% in Q8
appendAggSample(buf, 0, reinterpret_cast<uint8_t*>(&pct_data),
sizeof(pct_data));
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[49]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- QueryPerInstanceGPMMetrics: valid metricId BANDWIDTH (4764-4776) ------
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetrics_ValidMetricId_Bandwidth)
{
CLI::App app;
setupTelemetryCommands(app);
// metricId=8 is GPMMetricsUnit::BANDWIDTH
parseSubcmdArgs(app, "QueryPerInstanceGPMMetrics",
{"-r", "0", "-g", "0", "-c", "0", "-i", "8", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
// decode_aggregate_gpm_metric_bandwidth_data expects 8 bytes (uint64_t)
uint64_t bw = htole64(1024ULL * 1024 * 128);
appendAggSample(buf, 0, reinterpret_cast<uint8_t*>(&bw), sizeof(bw));
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[49]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- QueryPerInstanceGPMMetricsV2: valid metricId (4913-4914) ---------------
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetricsV2_ValidMetricId)
{
CLI::App app;
setupTelemetryCommands(app);
// metricId=0 is GPMMetricsUnit::PERCENTAGE
parseSubcmdArgs(app, "QueryPerInstanceGPMMetricsV2",
{"-r", "0", "-g", "0", "-c", "0", "-i", "0", "-b", "1"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint32_t pct_data = htole32(static_cast<uint32_t>(75.0 * 256));
appendAggSample(buf, 0, reinterpret_cast<uint8_t*>(&pct_data),
sizeof(pct_data));
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[50]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- GetPCIePortConfig: aggregate handler all paths (4957-4996) -------------
// PCIe preset tag (0) with correct size (1 byte) → success path 4967-4983
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_PresetTag_Success)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
// Test all preset tags 0-3 with 1 byte each
for (uint8_t tag = 0; tag <= 3; ++tag)
{
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t preset_byte = 0xAB; // preset0=0xB, preset1=0xA
appendAggSample(buf, tag, &preset_byte, 1);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[53]->parseResponseMsg(
msg, buf.size() - sizeof(nsm_msg_hdr)));
}
}
// PCIe_Tx_Amplitude tag (4) with 1 byte → success path 4984-4996
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_TxAmplitude_Success)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t amp_byte = 0x05;
appendAggSample(buf, 4, &amp_byte, 1); // tag=4 is PCIe_Tx_Amplitude
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[53]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// Unknown tag (5) → NSM_SW_ERROR_DATA path 4960-4964
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_UnknownTag_Error)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[1]{};
appendAggSample(buf, 5, d, 1); // tag=5 not in tagToPropertyMap
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[53]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// PCIe preset with wrong size (2 bytes) → error path 4977
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_PresetTag_BadData)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[2]{}; // wrong size: expects 1 byte
appendAggSample(buf, 0, d, 2);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[53]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// PCIe_Tx_Amplitude with wrong size (2 bytes) → error path 4991
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_TxAmplitude_BadData)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0"});
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_aggregate_resp(0, 0, NSM_SUCCESS, 1, msg);
uint8_t d[2]{}; // wrong size: expects 1 byte
appendAggSample(buf, 4, d, 2);
msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(
commands[53]->parseResponseMsg(msg, buf.size() - sizeof(nsm_msg_hdr)));
}
// ---- SetPCIePortConfig: sampleCount mismatch triggers error path (line 5066)
// sampleCount=1 means 1*sizeof(nsm_aggregate_resp_sample)=3 bytes expected,
// but sampleData has only 1 byte → condition true → return NSM_SW_ERROR_DATA
TEST(NsmTelemetryCmdParse, SetPCIePortConfig_SampleCountMismatch)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0", "-c", "1", "-d", "0"});
// createRequestMsg returns error code without throwing
EXPECT_NO_THROW(commands[54]->createRequestMsg());
}
// ---- GetRowRemapState with flags set ----------------------------------------
// GetRowRemapState with bit0=1 → line 4025 (RowRemappingFailureState = true)
TEST(NsmTelemetryCmdParse, GetRowRemapState_Bit0Set)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
flags.bits.bit0 = 1;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_row_remap_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_row_remap_state_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[39]->parseResponseMsg(msg, buf.size()));
}
// GetRowRemapState with bit1=1 → line 4033 (RowRemappingPendingState = true)
TEST(NsmTelemetryCmdParse, GetRowRemapState_Bit1Set)
{
CLI::App app;
setupTelemetryCommands(app);
bitfield8_t flags{};
flags.bits.bit1 = 1;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_row_remap_state_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_row_remap_state_resp(0, NSM_SUCCESS, ERR_NULL, &flags, msg);
EXPECT_NO_THROW(commands[39]->parseResponseMsg(msg, buf.size()));
}
// ---- SetPowerLimit MODULE branch (createRequestMsg, line 3817-3820) ---------
TEST(NsmTelemetryCmdParse, SetPowerLimit_ModuleBranch)
{
CLI::App app;
setupTelemetryCommands(app);
// powerLimitId = MODULE (1)
parseSubcmdArgs(app, "SetPowerLimit",
{"-i", "1", "-a", "0", "-p", "0", "-l", "100000"});
EXPECT_NO_THROW(commands[34]->createRequestMsg());
}
// ---- GetPowerLimit MODULE branch (createRequestMsg, line 3886-3888) ---------
TEST(NsmTelemetryCmdParse, GetPowerLimit_ModuleBranch)
{
CLI::App app;
setupTelemetryCommands(app);
// powerLimitId = MODULE (1)
parseSubcmdArgs(app, "GetPowerLimit", {"-i", "1"});
EXPECT_NO_THROW(commands[35]->createRequestMsg());
}
// ============================================================================
// Error-path tests: pass a truncated buffer so decode fails (rc !=
// NSM_SW_SUCCESS) This covers the else/error branch of all parseResponseMsg
// implementations.
// ============================================================================
static std::vector<uint8_t> makeTruncatedResp()
{
// A buffer with header + error response bytes — too small for any
// actual response payload, but large enough for decode_reason_code_and_cc.
return std::vector<uint8_t>(sizeof(nsm_msg_hdr) + NSM_RESPONSE_ERROR_LEN,
0);
}
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[0]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryPortCharacteristics_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[1]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryPortStatus_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[2]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryPortsAvailable_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[3]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetPortDisableFuture_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[4]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetFabricManagerState_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[5]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPortDisableFuture_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[6]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPowerMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[7]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetPowerMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[8]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetSwitchIsolationMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[9]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetSwitchIsolationMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[10]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetInventoryInformation_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[11]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetTemperatureReading_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[12]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, ReadThermalParameter_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[13]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetCurrentPowerDraw_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[14]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetMaxObservedPower_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[15]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetCurrentEnergyCount_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[16]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetVoltage_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[17]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetAltitudePressure_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[18]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetDriverInfo_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[19]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetMigMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[20]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetMigMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[21]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetEccMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[22]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetEccMode_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[23]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetEccErrorCounts_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[24]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetClockLimit_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[25]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetEDPpScalingFactors_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[26]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetEDPpScalingFactors_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[27]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryVectorGroupTelemetry_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[29]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse,
QueryAvailableAndClearableScalarGroup_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[30]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, PcieFundamentalReset_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[31]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, ClearScalarDataSource_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[32]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetClockLimit_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[33]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetPowerLimit_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[34]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPowerLimit_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[35]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetCurrClockFreq_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[36]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetAccumGpuUtilTime_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[37]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetProcessorThrottleReason_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[38]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetRowRemapState_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[39]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetRowRemappingCounts_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[40]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetRowRemapAvailability_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[41]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetLeakDetectionInfo_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[42]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetLeakDetectionThresholds_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[43]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetMemoryCapacityUtil_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[44]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetCurrentUtilization_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[45]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetClockOutputEnableState_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[46]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryAggregatedGPMMetrics_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[48]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetrics_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[49]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryPerInstanceGPMMetricsV2_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[50]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetViolationDuration_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[51]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetListAvailablePciePorts_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[52]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPCIePortConfig_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[53]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, SetPCIePortConfig_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[54]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse,
QueryMultiportScalarGroupTelemetry_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[55]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetEthPortTelemetryCounter_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[56]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPortNetworkAddresses_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[57]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPortEccCounters_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[58]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPowerSmoothingFeatureInfoV2_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[59]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPowerSmoothingCurrentProfile_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[60]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse,
GetPowerSmoothingAdminOverrideProfile_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[61]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, GetPowerSmoothingPresetProfile_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[62]->parseResponseMsg(msg, buf.size()));
}
// ---- printPortTeleInfo: all counter bits set to 1 --------------------------
// Covers the "true" branch of every if (portData->supported_counter.X) check.
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_AllCounterBitsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
struct nsm_port_counter_data portData{};
// Set all supported_counter bits to 1 so every if-branch is taken.
memset(&portData.supported_counter, 0xFF,
sizeof(portData.supported_counter));
portData.port_rcv_pkts = 1;
portData.port_rcv_data = 2;
portData.port_multicast_rcv_pkts = 3;
portData.port_unicast_rcv_pkts = 4;
portData.port_malformed_pkts = 5;
portData.vl15_dropped = 6;
portData.port_rcv_errors = 7;
portData.port_xmit_pkts = 8;
portData.port_xmit_pkts_vl15 = 9;
portData.port_xmit_data = 10;
portData.port_xmit_data_vl15 = 11;
portData.port_unicast_xmit_pkts = 12;
portData.port_multicast_xmit_pkts = 13;
portData.port_bcast_xmit_pkts = 14;
portData.port_xmit_discard = 15;
portData.port_neighbor_mtu_discards = 16;
portData.port_rcv_ibg2_pkts = 17;
portData.port_xmit_ibg2_pkts = 18;
portData.symbol_ber = 19;
portData.link_error_recovery_counter = 20;
portData.link_downed_counter = 21;
portData.port_rcv_remote_physical_errors = 22;
portData.port_rcv_switch_relay_errors = 23;
portData.QP1_dropped = 24;
portData.xmit_wait = 25;
portData.effective_ber = 26;
portData.total_raw_error = 27;
portData.effective_error = 28;
portData.symbol_error = 29;
portData.total_raw_ber = 30;
portData.unintentional_link_down_count = 31;
portData.intentional_link_down_count = 32;
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp) +
sizeof(nsm_port_counter_data));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_get_port_telemetry_counter_resp(0, NSM_SUCCESS, ERR_NULL, &portData,
msg);
EXPECT_NO_THROW(commands[0]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryScalarGroupTelemetry Group 1: CommonClock mode --------------------
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group1_CommonClockMode)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "1"});
struct nsm_query_scalar_group_telemetry_group_1 data{};
data.clock_mode = NSM_PCIE_CLOCK_MODE_COMMON;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_1_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group1_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryScalarGroupTelemetry Group 1: Unknown clock mode (default) --------
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group1_UnknownClockMode)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "1"});
struct nsm_query_scalar_group_telemetry_group_1 data{};
data.clock_mode = 99; // Unknown → default branch
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_1_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group1_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryScalarGroupTelemetry Group 7: success path (various port types) ---
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group7_Endpoint)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
struct nsm_query_scalar_group_telemetry_group_7 data{};
data.port_type = NSM_PCIE_PORT_TYPE_ENDPOINT;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_7_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group7_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group7_RootPort)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
struct nsm_query_scalar_group_telemetry_group_7 data{};
data.port_type = NSM_PCIE_PORT_TYPE_ROOT_PORT;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_7_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group7_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group7_UpstreamPort)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
struct nsm_query_scalar_group_telemetry_group_7 data{};
data.port_type = NSM_PCIE_PORT_TYPE_UPSTREAM;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_7_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group7_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group7_DownstreamPort)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
struct nsm_query_scalar_group_telemetry_group_7 data{};
data.port_type = NSM_PCIE_PORT_TYPE_DOWNSTREAM;
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_7_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group7_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
TEST(NsmTelemetryCmdParse, QueryScalarGroupTelemetry_Group7_UnknownPortType)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "QueryScalarGroupTelemetry", {"-d", "0", "-g", "7"});
struct nsm_query_scalar_group_telemetry_group_7 data{};
data.port_type = 99; // Unknown → default branch
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) +
sizeof(nsm_query_scalar_group_telemetry_v1_group_7_resp));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
encode_query_scalar_group_telemetry_v1_group7_resp(0, NSM_SUCCESS, ERR_NULL,
&data, msg);
EXPECT_NO_THROW(commands[28]->parseResponseMsg(msg, buf.size()));
}
// ---- QueryVectorGroupTelemetry Group 1: error path --------------------------
// The existing ParseResponseError test runs with groupId=2 (default case).
// This test explicitly sets groupId=1 and passes a truncated buffer so the
// decode-failure branch inside the GROUP_ID_1 case is reached.
TEST(NsmTelemetryCmdParse, QueryVectorGroupTelemetry_Group1_ParseResponseError)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(
app, "QueryVectorGroupTelemetry",
{"-t", "0", "-u", "0", "-i", "0", "-g", "1", "-s", "1", "-l", "0"});
auto buf = makeTruncatedResp();
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[29]->parseResponseMsg(msg, buf.size()));
}
// ---- SetPCIePortConfig: parseResponseMsg cc error path ----------------------
// A 9-byte buffer (nsm_msg_hdr + nsm_common_non_success_resp) with
// completion_code=NSM_ERROR makes decode_reason_code_and_cc succeed but return
// cc!=NSM_SUCCESS, so the error branch at lines 5267-5272 is taken.
TEST(NsmTelemetryCmdParse, SetPCIePortConfig_ParseResponseCcError)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "SetPCIePortConfig",
{"-p", "0", "-t", "0", "-i", "0", "-c", "0", "-d", "0"});
std::vector<uint8_t> buf(
sizeof(nsm_msg_hdr) + sizeof(nsm_common_non_success_resp), 0);
// Set completion_code (byte 1 in payload) to NSM_ERROR so the error path
// inside parseResponseMsg is exercised.
buf[sizeof(nsm_msg_hdr) + 1] = NSM_ERROR;
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
EXPECT_NO_THROW(commands[54]->parseResponseMsg(msg, buf.size()));
}
// ---- GetPortTelemetryCounter: printPortTeleInfo null portData
// ---------------- Call printPortTeleInfo directly with nullptr to cover the
// null-check branch at lines 122-126 of nsm_telemetry_cmd.cpp.
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_NullPortData)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
auto* cmd = static_cast<GetPortTelemetryCounter*>(commands[0].get());
EXPECT_NO_THROW(cmd->printPortTeleInfo(0, nullptr));
}
// ---- GetPortTelemetryCounter: all counter flags set -------------------------
// Exercises the TRUE branch of every `if (portData->supported_counter.xxx)`
// check in printPortTeleInfo (lines 134-334 of nsm_telemetry_cmd.cpp).
// The existing success test uses a zeroed portData, so all counter checks take
// the FALSE branch. This test calls printPortTeleInfo directly with all
// supported_counter bits set to avoid encode/decode stripping the flags.
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_AllCounterFlagsSet)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
struct nsm_port_counter_data portData{};
// Set all supported_counter bits so every flag-guarded branch is taken
memset(&portData.supported_counter, 0xFF,
sizeof(portData.supported_counter));
portData.port_rcv_pkts = 1;
portData.port_rcv_data = 2;
portData.port_multicast_rcv_pkts = 3;
portData.port_unicast_rcv_pkts = 4;
portData.port_malformed_pkts = 5;
portData.vl15_dropped = 6;
portData.port_rcv_errors = 7;
portData.port_xmit_pkts = 8;
// Call printPortTeleInfo directly to bypass encode/decode
auto* cmd = static_cast<GetPortTelemetryCounter*>(commands[0].get());
EXPECT_NO_THROW(cmd->printPortTeleInfo(sizeof(portData), &portData));
}
// ---- GetPortTelemetryCounter: decode ok but cc = NSM_ERROR ------------------
// Covers the missing branch at L104 where rc==NSM_SW_SUCCESS but
// cc!=NSM_SUCCESS (the second `&&` sub-condition fails, directing to the
// else/error path).
TEST(NsmTelemetryCmdParse, GetPortTelemetryCounter_ParseResponseCcError)
{
CLI::App app;
setupTelemetryCommands(app);
parseSubcmdArgs(app, "GetPortTelemetryCounter", {"-p", "0"});
struct nsm_port_counter_data portData{};
std::vector<uint8_t> buf(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp) +
sizeof(nsm_port_counter_data));
auto* msg = reinterpret_cast<nsm_msg*>(buf.data());
// Encode with NSM_ERROR: decode succeeds (rc=NSM_SW_SUCCESS) but cc !=
// NSM_SUCCESS
encode_get_port_telemetry_counter_resp(0, NSM_ERROR, ERR_NULL, &portData,
msg);
EXPECT_NO_THROW(commands[0]->parseResponseMsg(msg, buf.size()));
}
} // namespace nsmtool::telemetry