| /* |
| * 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 "base.h" |
| #include "device-configuration.h" |
| #include "diagnostics.h" |
| #include "pci-links.h" |
| #include "platform-environmental.h" |
| |
| #include "utils.hpp" |
| |
| #include <functional> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| using ::testing::Test; |
| |
| #define private public |
| #define protected public |
| #include "mockupResponder.hpp" |
| class MockupResponderTest : public Test |
| { |
| private: |
| template <typename ResponseStruct> |
| void test( |
| const nsm_msg* requestMsg, size_t requestMsgLen, |
| std::function<std::optional<Response>(const nsm_msg*, size_t)> handler, |
| uint8_t command, ResponseStruct& response) |
| { |
| // Good Test |
| auto resp = handler(requestMsg, requestMsgLen); |
| |
| EXPECT_TRUE(resp.has_value()); |
| EXPECT_EQ(resp.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(ResponseStruct)); |
| |
| auto msg = reinterpret_cast<nsm_msg*>(resp.value().data()); |
| EXPECT_GE(sizeof(ResponseStruct), sizeof(nsm_common_resp)); |
| auto common = reinterpret_cast<nsm_common_resp*>(msg->payload); |
| EXPECT_EQ(command, common->command); |
| EXPECT_EQ(sizeof(ResponseStruct) - sizeof(nsm_common_resp), |
| common->data_size); |
| response = *reinterpret_cast<ResponseStruct*>(msg->payload); |
| |
| // Bad tests |
| resp = handler(nullptr, requestMsgLen); |
| EXPECT_FALSE(resp.has_value()); |
| resp = handler(requestMsg, requestMsgLen - 1); |
| EXPECT_FALSE(resp.has_value()); |
| |
| auto badRequest = Request((uint8_t*)requestMsg, |
| (uint8_t*)requestMsg + requestMsgLen); |
| auto badRequestMsg = reinterpret_cast<nsm_msg*>(badRequest.data()); |
| badRequestMsg->hdr.ocp_type = 0; |
| resp = handler(badRequestMsg, requestMsgLen); |
| EXPECT_FALSE(resp.has_value()); |
| } |
| |
| template <typename ResponseStruct> |
| void |
| test(const nsm_msg* requestMsg, size_t requestMsgLen, |
| std::function<std::optional<Response>(const nsm_msg*, size_t, bool, |
| std::optional<Request>&)> |
| handler, |
| uint8_t command, ResponseStruct& response) |
| { |
| std::optional<Request> longRunningEvent; |
| // test as not long running |
| test(requestMsg, requestMsgLen, |
| [&handler, &longRunningEvent](const nsm_msg* request, size_t len) { |
| return handler(request, len, false, longRunningEvent); |
| }, command, response); |
| |
| // test as long running |
| auto resp = handler(requestMsg, requestMsgLen, true, longRunningEvent); |
| |
| EXPECT_TRUE(resp.has_value()); |
| EXPECT_EQ(resp.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp)); |
| auto respMsg = reinterpret_cast<nsm_msg*>(resp.value().data()); |
| auto commonResp = reinterpret_cast<nsm_common_resp*>(respMsg->payload); |
| EXPECT_EQ(command, commonResp->command); |
| EXPECT_EQ(NSM_ACCEPTED, commonResp->completion_code); |
| EXPECT_EQ(0, commonResp->reserved); |
| EXPECT_EQ(0, commonResp->data_size); |
| |
| EXPECT_TRUE(longRunningEvent.has_value()); |
| EXPECT_EQ(longRunningEvent.value().size(), |
| sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN + |
| sizeof(nsm_long_running_resp) + sizeof(ResponseStruct) - |
| sizeof(nsm_common_resp)); |
| } |
| |
| protected: |
| MockupResponderTest() : event(sdeventplus::Event::get_default()) |
| |
| { |
| init(30, NSM_DEV_ID_GPU, 2); |
| } |
| |
| uint8_t instanceId = 0; |
| sdeventplus::Event event; |
| boost::asio::io_context io; |
| std::shared_ptr<sdbusplus::asio::connection> systemBus; |
| std::shared_ptr<sdbusplus::asio::object_server> objServer; |
| std::shared_ptr<MockupResponder::MockupResponder> mockupResponder; |
| |
| void init(eid_t eid, uint8_t deviceType, uint8_t instanceId) |
| { |
| this->instanceId = instanceId; |
| systemBus = std::make_shared<sdbusplus::asio::connection>(io); |
| objServer = std::make_shared<sdbusplus::asio::object_server>(systemBus); |
| mockupResponder = std::make_shared<MockupResponder::MockupResponder>( |
| true, event, *objServer, eid, deviceType, instanceId); |
| } |
| |
| void testProperty(uint8_t propertyIdentifier, |
| const std::string& expectedValue) |
| { |
| // get property |
| auto res = mockupResponder->getProperty(propertyIdentifier); |
| EXPECT_NE(res.size(), 0); |
| |
| // verify property value |
| std::string returnedValue((char*)res.data(), res.size()); |
| EXPECT_STREQ(returnedValue.c_str(), expectedValue.c_str()); |
| } |
| void testProperty(uint8_t propertyIdentifier, uint32_t expectedValue) |
| { |
| // get property |
| auto res = mockupResponder->getProperty(propertyIdentifier); |
| EXPECT_EQ(res.size(), sizeof(uint32_t)); |
| |
| // verify property value |
| uint32_t returnedValue = htole32(*(uint32_t*)res.data()); |
| EXPECT_EQ(returnedValue, expectedValue); |
| } |
| |
| using MockupResponderFunction = std::optional<Response> ( |
| MockupResponder::MockupResponder::*)(const nsm_msg*, size_t); |
| |
| template <typename RequestPayload, typename ResponseStruct, |
| typename MockupFunction> |
| void test(std::function<int(uint8_t, const RequestPayload*, nsm_msg*)> |
| encodeRequestFunction, |
| RequestPayload& requestPayload, MockupFunction handlerFunction, |
| uint8_t command, ResponseStruct& response) |
| { |
| Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req) + |
| sizeof(RequestPayload), |
| 0); |
| auto requestMsg = reinterpret_cast<nsm_msg*>(request.data()); |
| auto rc = encodeRequestFunction( |
| instanceId, const_cast<const RequestPayload*>(&requestPayload), |
| requestMsg); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| auto handler = std::bind_front(handlerFunction, mockupResponder.get()); |
| test(requestMsg, request.size(), handler, command, response); |
| } |
| template <typename RequestPayload, typename MockupFunction> |
| void test(std::function<int(uint8_t, RequestPayload, nsm_msg*)> |
| encodeRequestFunction, |
| RequestPayload requestPayload, MockupFunction handlerFunction, |
| uint8_t command) |
| { |
| Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req) + |
| sizeof(RequestPayload)); |
| auto requestMsg = reinterpret_cast<nsm_msg*>(request.data()); |
| auto rc = encodeRequestFunction(instanceId, requestPayload, requestMsg); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| nsm_common_resp response; |
| auto handler = std::bind_front(handlerFunction, mockupResponder.get()); |
| test(requestMsg, request.size(), handler, command, response); |
| EXPECT_EQ(NSM_SUCCESS, response.completion_code); |
| } |
| template <typename ResponseStruct, typename MockupFunction> |
| void test(std::function<int(uint8_t, nsm_msg*)> encodeRequestFunction, |
| MockupFunction handlerFunction, uint8_t command, |
| ResponseStruct& response) |
| { |
| Request request(sizeof(nsm_msg_hdr) + sizeof(nsm_common_req)); |
| auto requestMsg = reinterpret_cast<nsm_msg*>(request.data()); |
| auto rc = encodeRequestFunction(instanceId, requestMsg); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| auto handler = std::bind_front(handlerFunction, mockupResponder.get()); |
| test(requestMsg, request.size(), handler, command, response); |
| } |
| }; |
| |
| TEST_F(MockupResponderTest, goodTestGetPropertyTest) |
| { |
| testProperty(BOARD_PART_NUMBER, "MCX750500B-0D00_DK"); |
| testProperty(SERIAL_NUMBER, "SN123456789"); |
| testProperty(MARKETING_NAME, "NV123"); |
| testProperty(PRODUCT_LENGTH, 850); |
| testProperty(PRODUCT_WIDTH, 730); |
| testProperty(PRODUCT_HEIGHT, 2600); |
| testProperty(MINIMUM_DEVICE_POWER_LIMIT, 10000); |
| testProperty(MAXIMUM_DEVICE_POWER_LIMIT, 100000); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestUuidPropertyTest) |
| { |
| uuid_t expectedUuid("72000000-0000-0000-0000-000000000000"); |
| |
| // get Uuid property |
| auto res = mockupResponder->getProperty(DEVICE_GUID); |
| EXPECT_EQ(res.size(), 16); |
| // verify Uuid property value |
| auto uuidProperty = utils::convertUUIDToString(res); |
| EXPECT_STREQ(uuidProperty.substr(2).c_str(), |
| expectedUuid.substr(2).c_str()); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestPowerSupplyStatusTest) |
| { |
| const uint8_t expectedStatus = 0b00110011; |
| std::vector<uint8_t> requestMsg( |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req)); |
| |
| auto request = reinterpret_cast<nsm_msg*>(requestMsg.data()); |
| fpga_diagnostics_settings_data_index data_index = GET_POWER_SUPPLY_STATUS; |
| |
| auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| |
| auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler( |
| request, requestMsg.size()); |
| |
| EXPECT_TRUE(res.has_value()); |
| EXPECT_EQ(res.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_supply_status_resp)); |
| |
| auto response = reinterpret_cast<nsm_msg*>(res.value().data()); |
| auto resp = (nsm_get_power_supply_status_resp*)response->payload; |
| |
| EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command); |
| EXPECT_EQ(expectedStatus, resp->power_supply_status); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestGpuPresenceTest) |
| { |
| uint32_t expectedPresence = 0b11111111; |
| std::vector<uint8_t> requestMsg( |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req)); |
| |
| auto request = reinterpret_cast<nsm_msg*>(requestMsg.data()); |
| fpga_diagnostics_settings_data_index data_index = GET_GPU_PRESENCE; |
| |
| auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| |
| auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler( |
| request, requestMsg.size()); |
| |
| EXPECT_TRUE(res.has_value()); |
| EXPECT_EQ(res.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_presence_resp)); |
| |
| auto response = reinterpret_cast<nsm_msg*>(res.value().data()); |
| auto resp = (nsm_get_gpu_presence_resp*)response->payload; |
| |
| EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command); |
| EXPECT_EQ(expectedPresence, resp->presence); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestGpuPresenceAndPowerStatusTest) |
| { |
| uint32_t expectedPower = 0b11110111; |
| std::vector<uint8_t> requestMsg( |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_fpga_diagnostics_settings_req)); |
| |
| auto request = reinterpret_cast<nsm_msg*>(requestMsg.data()); |
| fpga_diagnostics_settings_data_index data_index = GET_GPU_POWER_STATUS; |
| |
| auto rc = encode_get_fpga_diagnostics_settings_req(0, data_index, request); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| |
| auto res = mockupResponder->getFpgaDiagnosticsSettingsHandler( |
| request, requestMsg.size()); |
| |
| EXPECT_TRUE(res.has_value()); |
| EXPECT_EQ(res.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_power_status_resp)); |
| |
| auto response = reinterpret_cast<nsm_msg*>(res.value().data()); |
| auto resp = (nsm_get_gpu_power_status_resp*)response->payload; |
| |
| EXPECT_EQ(NSM_GET_FPGA_DIAGNOSTICS_SETTINGS, resp->hdr.command); |
| EXPECT_EQ(expectedPower, resp->power_status); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestGetReconfigurationPermissionsV1Handler) |
| { |
| Request request(sizeof(nsm_msg_hdr) + |
| sizeof(nsm_get_reconfiguration_permissions_v1_req)); |
| |
| auto requestMsg = reinterpret_cast<nsm_msg*>(request.data()); |
| reconfiguration_permissions_v1_index setting_index = RP_IN_SYSTEM_TEST; |
| |
| auto rc = encode_get_reconfiguration_permissions_v1_req(0, setting_index, |
| requestMsg); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| |
| auto resp = mockupResponder->getReconfigurationPermissionsV1Handler( |
| requestMsg, request.size()); |
| |
| EXPECT_TRUE(resp.has_value()); |
| EXPECT_EQ(resp.value().size(), |
| sizeof(nsm_msg_hdr) + |
| sizeof(nsm_get_reconfiguration_permissions_v1_resp)); |
| |
| auto msg = reinterpret_cast<nsm_msg*>(resp.value().data()); |
| auto response = |
| reinterpret_cast<nsm_get_reconfiguration_permissions_v1_resp*>( |
| msg->payload); |
| |
| nsm_reconfiguration_permissions_v1 expected = {0, 0, 0, 0, 1, 0, 1}; |
| EXPECT_EQ(NSM_GET_RECONFIGURATION_PERMISSIONS_V1, response->hdr.command); |
| EXPECT_EQ(expected.host_oneshot, response->data.host_oneshot); |
| EXPECT_EQ(expected.host_persistent, response->data.host_persistent); |
| EXPECT_EQ(expected.host_flr_persistent, response->data.host_flr_persistent); |
| } |
| |
| TEST_F(MockupResponderTest, goodTestSetReconfigurationPermissionsV1Handler) |
| { |
| Request request(sizeof(nsm_msg_hdr) + |
| sizeof(nsm_set_reconfiguration_permissions_v1_req)); |
| |
| auto requestMsg = reinterpret_cast<nsm_msg*>(request.data()); |
| auto settingIndex = RP_IN_SYSTEM_TEST; |
| auto configuration = RP_ONESHOOT_HOT_RESET; |
| uint8_t permission = 0; |
| |
| auto rc = encode_set_reconfiguration_permissions_v1_req( |
| 0, settingIndex, configuration, permission, requestMsg); |
| EXPECT_EQ(rc, NSM_SW_SUCCESS); |
| |
| auto resp = mockupResponder->setReconfigurationPermissionsV1Handler( |
| requestMsg, request.size()); |
| |
| EXPECT_TRUE(resp.has_value()); |
| EXPECT_EQ(resp.value().size(), |
| sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp)); |
| |
| auto msg = reinterpret_cast<nsm_msg*>(resp.value().data()); |
| auto response = reinterpret_cast<nsm_common_resp*>(msg->payload); |
| |
| EXPECT_EQ(NSM_SET_RECONFIGURATION_PERMISSIONS_V1, response->command); |
| } |
| |
| TEST_F(MockupResponderTest, testGetErrorInjectionModeV1Handler) |
| { |
| nsm_get_error_injection_mode_v1_resp response; |
| test(&encode_get_error_injection_mode_v1_req, |
| &MockupResponder::MockupResponder::getErrorInjectionModeV1Handler, |
| NSM_GET_ERROR_INJECTION_MODE_V1, response); |
| EXPECT_EQ(mockupResponder->state.errorInjectionMode.mode, |
| response.data.mode); |
| EXPECT_EQ(mockupResponder->state.errorInjectionMode.flags.byte, |
| response.data.flags.byte); |
| } |
| |
| TEST_F(MockupResponderTest, testGetSupportedErrorInjectionTypesHandler) |
| { |
| nsm_get_error_injection_types_mask_resp response; |
| test(&encode_get_supported_error_injection_types_v1_req, |
| &MockupResponder::MockupResponder:: |
| getSupportedErrorInjectionTypesV1Handler, |
| NSM_GET_SUPPORTED_ERROR_INJECTION_TYPES_V1, response); |
| for (const auto& [type, _] : |
| mockupResponder->state.errorInjection[NSM_DEV_ID_GPU]) |
| { |
| EXPECT_TRUE(response.data.mask[type / 8] & (1 << (type % 8))); |
| } |
| } |
| |
| TEST_F(MockupResponderTest, testSetCurrentErrorInjectionTypesHandler) |
| { |
| nsm_error_injection_types_mask data = {0, 0, 0, 0, 0, 0, 0, 0}; |
| nsm_common_resp response; |
| for (const auto& [type, _] : |
| mockupResponder->state.errorInjection[NSM_DEV_ID_GPU]) |
| { |
| data.mask[type / 8] |= (1 << (type % 8)); |
| } |
| test<nsm_error_injection_types_mask>( |
| &encode_set_current_error_injection_types_v1_req, data, |
| &MockupResponder::MockupResponder:: |
| setCurrentErrorInjectionTypesV1Handler, |
| NSM_SET_CURRENT_ERROR_INJECTION_TYPES_V1, response); |
| } |
| TEST_F(MockupResponderTest, testGetCurrentErrorInjectionTypesHandler) |
| { |
| nsm_get_error_injection_types_mask_resp response; |
| test(&encode_get_current_error_injection_types_v1_req, |
| &MockupResponder::MockupResponder:: |
| getCurrentErrorInjectionTypesV1Handler, |
| NSM_GET_CURRENT_ERROR_INJECTION_TYPES_V1, response); |
| for (const auto& [type, enabled] : |
| mockupResponder->state.errorInjection[NSM_DEV_ID_GPU]) |
| { |
| EXPECT_EQ(enabled, response.data.mask[type / 8] & (1 << (type % 8))); |
| } |
| } |
| |
| TEST_F(MockupResponderTest, testMigModeHandler) |
| { |
| nsm_get_MIG_mode_resp response; |
| test(&encode_get_MIG_mode_req, |
| &MockupResponder::MockupResponder::getMigModeHandler, NSM_GET_MIG_MODE, |
| response); |
| EXPECT_EQ(mockupResponder->state.migMode, response.flags.byte); |
| uint8_t data = 1; |
| test<uint8_t>(&encode_set_MIG_mode_req, data, |
| &MockupResponder::MockupResponder::setMigModeHandler, |
| NSM_SET_MIG_MODE); |
| test(&encode_get_MIG_mode_req, |
| &MockupResponder::MockupResponder::getMigModeHandler, NSM_GET_MIG_MODE, |
| response); |
| EXPECT_EQ(mockupResponder->state.migMode, response.flags.byte); |
| } |
| |
| TEST_F(MockupResponderTest, testEccModeHandler) |
| { |
| nsm_get_ECC_mode_resp response; |
| test(&encode_get_ECC_mode_req, |
| &MockupResponder::MockupResponder::getEccModeHandler, NSM_GET_ECC_MODE, |
| response); |
| EXPECT_EQ(mockupResponder->state.eccMode, response.flags.byte); |
| uint8_t data = 1; |
| test<uint8_t>(&encode_set_ECC_mode_req, data, |
| &MockupResponder::MockupResponder::setEccModeHandler, |
| NSM_SET_ECC_MODE); |
| test(&encode_get_ECC_mode_req, |
| &MockupResponder::MockupResponder::getEccModeHandler, NSM_GET_ECC_MODE, |
| response); |
| EXPECT_EQ(mockupResponder->state.eccMode, response.flags.byte); |
| } |
| |
| TEST_F(MockupResponderTest, testGetMemoryCapacityUtilHandler) |
| { |
| nsm_get_memory_capacity_util_resp response; |
| test(&encode_get_memory_capacity_util_req, |
| &MockupResponder::MockupResponder::getMemoryCapacityUtilHandler, |
| NSM_GET_MEMORY_CAPACITY_UTILIZATION, response); |
| } |
| |
| TEST_F(MockupResponderTest, testGetCurrentUtilizationHandler) |
| { |
| nsm_get_current_utilization_resp response; |
| test(&encode_get_current_utilization_req, |
| &MockupResponder::MockupResponder::getCurrentUtilizationHandler, |
| NSM_GET_CURRENT_UTILIZATION, response); |
| } |
| |
| TEST_F(MockupResponderTest, testGetViolationDurationHandler) |
| { |
| nsm_get_violation_duration_resp response; |
| test(&encode_get_violation_duration_req, |
| &MockupResponder::MockupResponder::getViolationDurationHandler, |
| NSM_GET_VIOLATION_DURATION, response); |
| } |
| |
| TEST_F(MockupResponderTest, testListAvailablePciePortsHandler) |
| { |
| nsm_list_available_pcie_ports_resp response; |
| test(&encode_list_available_pcie_ports_req, |
| &MockupResponder::MockupResponder::getListAvailablePciePortsHandler, |
| NSM_LIST_AVAILABLE_PCIE_PORTS, response); |
| } |
| |
| struct QueryScalarGroupTelemetryV1GroupReqData |
| { |
| uint8_t deviceId; |
| uint8_t groupId; |
| } __attribute__((packed)); |
| |
| auto encodeQueryScalarGroupTelemetryV1Req() |
| { |
| return |
| [&](uint8_t instanceId, |
| const QueryScalarGroupTelemetryV1GroupReqData* data, nsm_msg* msg) { |
| return encode_query_scalar_group_telemetry_v1_req( |
| instanceId, data->deviceId, data->groupId, msg); |
| }; |
| } |
| |
| TEST_F(MockupResponderTest, testQueryScalarGroup10TelemetryHandler) |
| { |
| QueryScalarGroupTelemetryV1GroupReqData data = {0, GROUP_ID_10}; |
| nsm_query_scalar_group_telemetry_v1_group_10_resp response; |
| test<QueryScalarGroupTelemetryV1GroupReqData>( |
| encodeQueryScalarGroupTelemetryV1Req(), data, |
| &MockupResponder::MockupResponder::queryScalarGroupTelemetryHandler, |
| NSM_QUERY_SCALAR_GROUP_TELEMETRY_V1, response); |
| } |
| TEST_F(MockupResponderTest, testMultiportQueryScalarGroup10TelemetryHandler) |
| { |
| nsm_multiport_query_scalar_group_telemetry_v2_req_data data = { |
| 0, NSM_PORT_TYPE_UPSTREAM, 0, GROUP_ID_10}; |
| nsm_query_scalar_group_telemetry_v1_group_10_resp response; |
| test<nsm_multiport_query_scalar_group_telemetry_v2_req_data>( |
| &encode_multiport_query_scalar_group_telemetry_v2_req, data, |
| &MockupResponder::MockupResponder:: |
| queryMultiportScalarGroupTelemetryHandler, |
| NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2, response); |
| } |