diff --git a/tests/forwarding/smoke_test.cc b/tests/forwarding/smoke_test.cc index b1b84837..1bf37ba7 100644 --- a/tests/forwarding/smoke_test.cc +++ b/tests/forwarding/smoke_test.cc @@ -72,22 +72,6 @@ TEST_P(SmokeTestFixture, DISABLED_ModifyWorks) { ASSERT_OK(pdpi::ClearTableEntries(SutP4RuntimeSession())); } -TEST_P(SmokeTestFixture, InstallDefaultRouteForEmptyStringVrfShouldSucceed) { - GetMirrorTestbed().Environment().SetTestCaseID( - "2d67413c-9b6e-4187-84d4-c9313b84cab3"); - const sai::TableEntry pd_entry = gutil::ParseProtoOrDie( - R"pb( - ipv4_table_entry { - match { vrf_id: "" } - action { drop {} } - } - )pb"); - - ASSERT_OK_AND_ASSIGN(const p4::v1::TableEntry pi_entry, - pdpi::PartialPdTableEntryToPiTableEntry(IrP4Info(), pd_entry)); - ASSERT_OK(pdpi::InstallPiTableEntry(SutP4RuntimeSession(), pi_entry)); -} - // TODO: Enable once the bug is fixed. TEST_P(SmokeTestFixture, DISABLED_Bug181149419) { GetMirrorTestbed().Environment().SetTestCaseID( diff --git a/tests/thinkit_gnmi_interface_tests.cc b/tests/thinkit_gnmi_interface_tests.cc index 0bf54e7d..0053e8f7 100644 --- a/tests/thinkit_gnmi_interface_tests.cc +++ b/tests/thinkit_gnmi_interface_tests.cc @@ -410,7 +410,8 @@ void BreakoutDuringPortInUse(thinkit::Switch& sut, grpc::ClientContext context; ASSERT_OK_AND_ASSIGN(auto port_index, GetPortIndex(platform_json_contents, port_info.port_name)); - ASSERT_OK(GetBreakoutModeConfigFromString(req, port_index, + ASSERT_OK(GetBreakoutModeConfigFromString(req, sut_gnmi_stub, port_index, + port_info.port_name, port_info.supported_breakout_mode)); // Apply breakout config on port. Expect the set operation to fail @@ -454,8 +455,10 @@ void BreakoutDuringPortInUse(thinkit::Switch& sut, non_existing_port_list)); // Restore original port breakout config on port under test. - ASSERT_OK(GetBreakoutModeConfigFromString(req, port_index, + ASSERT_OK(GetBreakoutModeConfigFromString(req, sut_gnmi_stub, port_index, + port_info.port_name, port_info.curr_breakout_mode)); + LOG(INFO) << "Restoring original breakout mode " << port_info.curr_breakout_mode << " on port " << port_info.port_name << " on DUT"; diff --git a/tests/thinkit_gnmi_interface_util.cc b/tests/thinkit_gnmi_interface_util.cc index 3e28d7c7..4d6bd56b 100644 --- a/tests/thinkit_gnmi_interface_util.cc +++ b/tests/thinkit_gnmi_interface_util.cc @@ -15,6 +15,8 @@ #include "absl/strings/match.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" @@ -35,15 +37,11 @@ using ::nlohmann::json; } // namespace -void StripSymbolFromString(std::string& str, const char symbol) { - str.erase(remove(str.begin(), str.end(), symbol), str.end()); -} - -std::string ConstructSupportedBreakoutMode(std::string& num_breakouts, - std::string& breakout_speed) { - StripSymbolFromString(num_breakouts, ' '); - StripSymbolFromString(breakout_speed, ' '); - return absl::StrCat(num_breakouts, "x", breakout_speed); +std::string ConstructSupportedBreakoutMode(absl::string_view num_breakouts, + absl::string_view breakout_speed) { + std::string breakout_mode = absl::StrCat(num_breakouts, "x", breakout_speed); + StripSymbolFromString(breakout_mode, ' '); + return breakout_mode; } absl::StatusOr> GetSupportedBreakoutModesForPort( @@ -105,8 +103,8 @@ absl::StatusOr> GetSupportedBreakoutModesForPort( if (breakout_type == BreakoutType::kChannelized) { for (const auto& mode : modes) { // A breakout mode is a channelized mode if it is either a mixed mode (eg. - // 1x200G+2x100G) or it results in more than one number of interfaces - // (eg. 2x200G). + // 1x200G(4)+2x100G(4)) or it results in more than one number of + // interfaces (eg. 2x200G). auto num_breakouts_str = mode.substr(0, mode.find('x')); int num_breakouts; if (!absl::SimpleAtoi(num_breakouts_str, &num_breakouts)) { @@ -124,20 +122,20 @@ absl::StatusOr> GetSupportedBreakoutModesForPort( } absl::StatusOr BreakoutResultsInSpeedChangeOnly( - const std::string& port, const std::string& curr_breakout_mode, + const std::string& port, const std::string& current_breakout_mode, const std::string& new_breakout_mode) { // Get list of interfaces for current and new breakout modes. - ASSIGN_OR_RETURN(auto curr_port_info, GetExpectedPortInfoForBreakoutMode( - port, curr_breakout_mode)); + ASSIGN_OR_RETURN(auto current_port_info, GetExpectedPortInfoForBreakoutMode( + port, current_breakout_mode)); ASSIGN_OR_RETURN(auto new_port_info, GetExpectedPortInfoForBreakoutMode(port, new_breakout_mode)); - for (auto& key : curr_port_info) { - if (!new_port_info.count(key.first)) { + for (const auto& [key, unused_val] : current_port_info) { + if (!new_port_info.count(key)) { return false; } } - for (auto& key : new_port_info) { - if (!curr_port_info.count(key.first)) { + for (const auto& [key, unused_val] : new_port_info) { + if (!current_port_info.count(key)) { return false; } } @@ -266,24 +264,24 @@ GetExpectedPortInfoForBreakoutMode(const std::string& port, } // For a mixed breakout mode, get "+" separated breakout groups. - // Eg. For a mixed breakout mode of "2x100G + 1x200G"; modes = {2x100G, - // 1x200G} + // Eg. For a mixed breakout mode of "2x100G(4) + 1x200G(4)"; modes = + // {2x100G(4), 1x200G(4)} std::vector modes = absl::StrSplit(breakout_mode, '+'); // Get maximum physical channels in a breakout group which is max // lanes per physical port/number of groups in a breakout mode. auto max_channels_in_group = kMaxPortLanes / modes.size(); auto port_number_str = port.substr(kEthernetLen); - int curr_port_number; - if (!absl::SimpleAtoi(port_number_str, &curr_port_number)) { + int current_port_number; + if (!absl::SimpleAtoi(port_number_str, ¤t_port_number)) { return gutil::InternalErrorBuilder().LogError() << "Failed to convert string (" << port_number_str << ") to integer"; } - if (curr_port_number % kMaxPortLanes != 0) { + if (current_port_number % kMaxPortLanes != 0) { return gutil::InternalErrorBuilder().LogError() << "Requested port (" << port << ") is not a parent port"; } - auto curr_physical_channel = 0; + auto current_physical_channel = 0; absl::flat_hash_map expected_breakout_info; for (auto& mode : modes) { @@ -298,13 +296,13 @@ GetExpectedPortInfoForBreakoutMode(const std::string& port, // For each resulting interface, construct the front panel interface name // using offset from the parent port. For a breakout mode of Ethernet0 => - // 2x100G+1x200G, the max channels per group would be 4 (8 max lanes per - // port/2 groups). Hence, breakout mode 2x100G (numBreakouts=2) would have - // an offset of 2 and 1x200G(numBreakouts=1) would have an offset of 1 + // 2x100(4)G+1x200G(4), the max channels per group would be 4 (8 max lanes + // per port/2 groups). Hence, breakout mode 2x100G (numBreakouts=2) would + // have an offset of 2 and 1x200G(numBreakouts=1) would have an offset of 1 // leading to interfaces Ethernet0, Ethernet2 for mode 2x100G and // Ethernet4 for mode 1x200G. for (int i = 0; i < num_breakouts; i++) { - auto port = absl::StrCat(kEthernet, std::to_string(curr_port_number)); + auto port = absl::StrCat(kEthernet, std::to_string(current_port_number)); // Populate expected physical channels for each port. // Physical channels are between 0 to 7. int offset = max_channels_in_group / num_breakouts; @@ -313,15 +311,15 @@ GetExpectedPortInfoForBreakoutMode(const std::string& port, << "Invalid breakout mode (" << breakout_mode << ") found"; } std::string physical_channels = "["; - for (int j = curr_physical_channel; j < offset + curr_physical_channel; - j++) { + for (int j = current_physical_channel; + j < offset + current_physical_channel; j++) { physical_channels += std::to_string(j); // Add comma after each but last entry. - if (j < offset + curr_physical_channel - 1) physical_channels += ","; + if (j < offset + current_physical_channel - 1) physical_channels += ","; } physical_channels += "]"; - curr_physical_channel += offset; - curr_port_number += offset; + current_physical_channel += offset; + current_port_number += offset; expected_breakout_info[port] = PortBreakoutInfo{physical_channels}; } } @@ -332,10 +330,11 @@ absl::StatusOr> GetBreakoutStateInfoForPort(gnmi::gNMI::StubInterface* sut_gnmi_stub, const std::string& port, absl::string_view breakout_mode) { - ASSIGN_OR_RETURN(auto port_info, + absl::flat_hash_map port_infos; + ASSIGN_OR_RETURN(port_infos, GetExpectedPortInfoForBreakoutMode(port, breakout_mode)); - for (auto& p : port_info) { - auto if_state_path = absl::StrCat("interfaces/interface[name=", p.first, + for (auto& [port_name, breakout_info] : port_infos) { + auto if_state_path = absl::StrCat("interfaces/interface[name=", port_name, "]/state/oper-status"); auto resp_parse_str = "openconfig-interfaces:oper-status"; ASSIGN_OR_RETURN( @@ -343,11 +342,11 @@ GetBreakoutStateInfoForPort(gnmi::gNMI::StubInterface* sut_gnmi_stub, GetGnmiStatePathInfo(sut_gnmi_stub, if_state_path, resp_parse_str), _ << "Failed to get GNMI state path value for oper-status for " "port " - << p.first); - p.second.oper_status = state_path_response; + << port_name); + breakout_info.oper_status = state_path_response; auto if_physical_channels_path = absl::StrCat( - "interfaces/interface[name=", p.first, "]/state/physical-channel"); + "interfaces/interface[name=", port_name, "]/state/physical-channel"); resp_parse_str = "openconfig-platform-transceiver:physical-channel"; ASSIGN_OR_RETURN( state_path_response, @@ -355,10 +354,10 @@ GetBreakoutStateInfoForPort(gnmi::gNMI::StubInterface* sut_gnmi_stub, resp_parse_str), _ << "Failed to get GNMI state path value for physical-channels for " "port " - << p.first); - p.second.physical_channels = state_path_response; + << port_name); + breakout_info.physical_channels = state_path_response; } - return port_info; + return port_infos; } absl::StatusOr GenerateComponentBreakoutConfig( @@ -378,8 +377,46 @@ absl::StatusOr GenerateComponentBreakoutConfig( return component_config; } +absl::StatusOr IsCopperPort(gnmi::gNMI::StubInterface* sut_gnmi_stub, + absl::string_view port) { + // Get transceiver name for the port. + auto state_path = + absl::StrCat("interfaces/interface[name=", port, "]/state/transceiver"); + auto resp_parse_str = "openconfig-platform-transceiver:transceiver"; + ASSIGN_OR_RETURN( + auto xcvrd_name, + GetGnmiStatePathInfo(sut_gnmi_stub, state_path, resp_parse_str), + _ << "Failed to get GNMI state path value for port transceiver for " + "port " + << port); + StripSymbolFromString(xcvrd_name, '\"'); + + // TODO: Replace with PMD type when supported. + // Get cable length for the port transceiver. + state_path = + absl::StrCat("components/component[name=", xcvrd_name, + "]/transceiver/state/openconfig-platform-ext:cable-length"); + resp_parse_str = "openconfig-platform-ext:cable-length"; + ASSIGN_OR_RETURN( + auto cable_length_str, + GetGnmiStatePathInfo(sut_gnmi_stub, state_path, resp_parse_str), + _ << "Failed to get GNMI state path value for cable-length for " + "port " + << port); + StripSymbolFromString(cable_length_str, '\"'); + + // Only cable lengths of copper ports are a positive value. + float cable_length; + if (!absl::SimpleAtof(cable_length_str, &cable_length)) { + return gutil::InternalErrorBuilder().LogError() + << "Failed to convert string (" << cable_length_str << ") to float"; + } + return (cable_length > 0); +} + absl::StatusOr GenerateInterfaceBreakoutConfig( - absl::string_view port, const int id, absl::string_view breakout_speed) { + absl::string_view port, const int id, absl::string_view breakout_speed, + const bool is_copper_port) { auto interface_config = absl::Substitute( R"pb({ "config": { @@ -406,18 +443,50 @@ absl::StatusOr GenerateInterfaceBreakoutConfig( } )pb", port, breakout_speed); + if (is_copper_port) { + interface_config = absl::Substitute( + R"pb({ + "config": { + "enabled": true, + "loopback-mode": false, + "mtu": 9216, + "name": "$0", + "type": "iana-if-type:ethernetCsmacd" + }, + "name": "$0", + "openconfig-if-ethernet:ethernet": { + "config": { + "port-speed": "openconfig-if-ethernet:SPEED_$1B", + "standalone-link-training": true + } + }, + "subinterfaces": { + "subinterface": + [ { + "config": { "index": 0 }, + "index": 0, + "openconfig-if-ip:ipv6": { + "unnumbered": { "config": { "enabled": true } } + } + }] + } + } + )pb", + port, breakout_speed); + } return interface_config; } absl::Status GetBreakoutModeConfigFromString( - gnmi::SetRequest& req, const absl::string_view port_index, + gnmi::SetRequest& req, gnmi::gNMI::StubInterface* sut_gnmi_stub, + const absl::string_view port_index, const absl::string_view intf_name, const absl::string_view breakout_mode) { std::string kBreakoutPath = absl::StrCat("components/component[name=1/", port_index, "]/port/breakout-mode"); // Get breakout groups corresponding to breakout mode. // For a mixed breakout mode, get "+" separated breakout groups. - // Eg. For a mixed breakout mode of "2x100G + 1x200G"; modes = {2x100G, - // 1x200G} + // Eg. For a mixed breakout mode of "2x100G(4) + 1x200G(4)"; modes = + // {2x100G(4), 1x200G(4)} std::vector modes = absl::StrSplit(breakout_mode, '+'); std::vector group_configs; std::vector interface_configs; @@ -425,14 +494,16 @@ absl::Status GetBreakoutModeConfigFromString( auto index = 0; // Get current port number. - int curr_port_number; - if (!absl::SimpleAtoi(port_index, &curr_port_number)) { + int current_port_number; + if (!absl::SimpleAtoi(port_index, ¤t_port_number)) { return gutil::InternalErrorBuilder().LogError() << "Failed to convert string (" << port_index << ") to integer"; } - curr_port_number = (curr_port_number - 1) * kMaxPortLanes; + current_port_number = (current_port_number - 1) * kMaxPortLanes; - for (auto& mode : modes) { + ASSIGN_OR_RETURN(bool is_copper_port, IsCopperPort(sut_gnmi_stub, intf_name)); + + for (const auto& mode : modes) { auto num_breakouts_str = mode.substr(0, mode.find('x')); int num_breakouts; if (!absl::SimpleAtoi(num_breakouts_str, &num_breakouts)) { @@ -440,7 +511,8 @@ absl::Status GetBreakoutModeConfigFromString( << "Failed to convert string (" << num_breakouts_str << ") to integer"; } - auto breakout_speed = mode.substr(mode.find('x') + 1); + auto xpos = mode.find('x'); + auto breakout_speed = mode.substr(xpos + 1, mode.find('(') - xpos - 1); auto num_physical_channels = max_channels_in_group / num_breakouts; ASSIGN_OR_RETURN( auto group_config, @@ -451,27 +523,20 @@ absl::Status GetBreakoutModeConfigFromString( // Get the interface config for all ports corresponding to current breakout // group. for (int i = 0; i < num_breakouts; i++) { - auto port = absl::StrCat(kEthernet, std::to_string(curr_port_number)); - ASSIGN_OR_RETURN(auto interfaceConfig, - GenerateInterfaceBreakoutConfig(port, curr_port_number, - breakout_speed)); - interface_configs.push_back(interfaceConfig); + auto port = absl::StrCat(kEthernet, std::to_string(current_port_number)); + ASSIGN_OR_RETURN( + auto interface_config, + GenerateInterfaceBreakoutConfig(port, current_port_number, + breakout_speed, is_copper_port)); + interface_configs.push_back(interface_config); int offset = max_channels_in_group / num_breakouts; - curr_port_number += offset; + current_port_number += offset; } index += 1; } - std::string componentConfig, interfaceConfig; - for (auto& group_config : group_configs) { - componentConfig += absl::StrCat(group_config, ","); - } - for (auto& interface_config : interface_configs) { - interfaceConfig += absl::StrCat(interface_config, ","); - } - // Pop the last comma from the component and interface config array. - componentConfig.pop_back(); - interfaceConfig.pop_back(); + std::string full_component_config = absl::StrJoin(group_configs, ","); + std::string full_interface_config = absl::StrJoin(interface_configs, ","); auto kBreakoutConfig = absl::Substitute( R"pb({ @@ -488,8 +553,8 @@ absl::Status GetBreakoutModeConfigFromString( }] } })pb", - interfaceConfig, absl::StrCat("1/", port_index), port_index, - componentConfig); + full_interface_config, absl::StrCat("1/", port_index), port_index, + full_component_config); // Build GNMI config set request for given port breakout mode. ASSIGN_OR_RETURN( req, BuildGnmiSetRequest("", GnmiSetType::kReplace, kBreakoutConfig)); @@ -497,66 +562,71 @@ absl::Status GetBreakoutModeConfigFromString( } std::vector GetNonExistingPortsAfterBreakout( - absl::flat_hash_map& orig_port_info, - absl::flat_hash_map& new_port_info, + const absl::flat_hash_map& + original_port_info, + const absl::flat_hash_map& new_port_info, bool expected_success) { - std::vector nonExistingPortList; - absl::flat_hash_map*orig_map = &orig_port_info, - *new_map = &new_port_info; + std::vector non_existing_ports; + const auto* original_map = &original_port_info; + const auto* new_map = &new_port_info; + if (!expected_success) { - orig_map = &new_port_info; - new_map = &orig_port_info; + original_map = &new_port_info; + new_map = &original_port_info; } - for (const auto& port : *orig_map) { - if (new_map->find(port.first) == new_map->end()) { - nonExistingPortList.push_back(port.first); + for (const auto& [port_name, unused] : *original_map) { + if (new_map->find(port_name) == new_map->end()) { + non_existing_ports.push_back(port_name); } } - return nonExistingPortList; + return non_existing_ports; } absl::Status ValidateBreakoutState( gnmi::gNMI::StubInterface* sut_gnmi_stub, - absl::flat_hash_map& expected_port_info, - std::vector& non_existing_ports_list) { + const absl::flat_hash_map& + expected_port_info, + const std::vector& non_existing_ports_list) { if (expected_port_info.empty()) { return gutil::InternalErrorBuilder().LogError() << "Expected port info map is empty"; } - for (const auto& port : expected_port_info) { + for (const auto& [port_name, breakout_info] : expected_port_info) { // Verify that the oper-status state path value is as expected. - auto if_state_path = absl::StrCat("interfaces/interface[name=", port.first, - "]/state/oper-status"); - auto resp_parse_str = "openconfig-interfaces:oper-status"; + auto interface_state_path = absl::StrCat( + "interfaces/interface[name=", port_name, "]/state/oper-status"); + auto response_parse_str = "openconfig-interfaces:oper-status"; ASSIGN_OR_RETURN( auto state_path_response, - GetGnmiStatePathInfo(sut_gnmi_stub, if_state_path, resp_parse_str), + GetGnmiStatePathInfo(sut_gnmi_stub, interface_state_path, + response_parse_str), _ << "Failed to get GNMI state path value for oper-status for " "port " - << port.first); - if (!absl::StrContains(state_path_response, port.second.oper_status)) { + << port_name); + if (!absl::StrContains(state_path_response, breakout_info.oper_status)) { return gutil::InternalErrorBuilder().LogError() << absl::StrCat("Port oper-status match failed for port ", - port.first, ". got: ", state_path_response, - ", want:", port.second.oper_status); + port_name, ". got: ", state_path_response, + ", want:", breakout_info.oper_status); } // Verify that the physical-channels state path value is as expected. - if_state_path = absl::StrCat("interfaces/interface[name=", port.first, - "]/state/physical-channel"); - resp_parse_str = "openconfig-platform-transceiver:physical-channel"; + interface_state_path = absl::StrCat("interfaces/interface[name=", port_name, + "]/state/physical-channel"); + response_parse_str = "openconfig-platform-transceiver:physical-channel"; ASSIGN_OR_RETURN( state_path_response, - GetGnmiStatePathInfo(sut_gnmi_stub, if_state_path, resp_parse_str), + GetGnmiStatePathInfo(sut_gnmi_stub, interface_state_path, + response_parse_str), _ << "Failed to get GNMI state path value for physical-channels for " "port " - << port.first); + << port_name); if (!absl::StrContains(state_path_response, - port.second.physical_channels)) { + breakout_info.physical_channels)) { return gutil::InternalErrorBuilder().LogError() << absl::StrCat("Physical channel match failed for port ", - port.first, ". got: ", state_path_response, - ", want: ", port.second.physical_channels); + port_name, ". got: ", state_path_response, + ", want: ", breakout_info.physical_channels); } } diff --git a/tests/thinkit_gnmi_interface_util.h b/tests/thinkit_gnmi_interface_util.h index 44fee3c6..5b27069a 100644 --- a/tests/thinkit_gnmi_interface_util.h +++ b/tests/thinkit_gnmi_interface_util.h @@ -31,9 +31,9 @@ namespace pins_test { -const int kMaxPortLanes = 8; -const int kEthernetLen = 8; -constexpr char kEthernet[] = "Ethernet"; +inline constexpr int kMaxPortLanes = 8; +inline constexpr int kEthernetLen = 8; +inline constexpr char kEthernet[] = "Ethernet"; // // PortBreakoutInfo contains physical channels and operational status for an // // interface. @@ -94,7 +94,8 @@ GetExpectedPortInfoForBreakoutMode(const std::string& port, // breakoutSpeed1 + numBreakouts2 x breakoutSpeed2 + ... Eg: "1x400G", 2x100G + // 1x200G" absl::Status GetBreakoutModeConfigFromString( - gnmi::SetRequest& req, const absl::string_view index, + gnmi::SetRequest& req, gnmi::gNMI::StubInterface* sut_gnmi_stub, + const absl::string_view port_index, const absl::string_view intf_name, const absl::string_view breakout_mode); // GetNonExistingPortsAfterBreakout returns list of ports that were part of a @@ -107,8 +108,9 @@ absl::Status GetBreakoutModeConfigFromString( // the port, ports in original breakout config that were not in new breakout // config should no longer exist as new breakout is now applied. std::vector GetNonExistingPortsAfterBreakout( - absl::flat_hash_map& orig_port_info, - absl::flat_hash_map& new_port_info, + const absl::flat_hash_map& + original_port_info, + const absl::flat_hash_map& new_port_info, bool expected_success); // ValidateBreakoutState checks the breakout related state paths with the @@ -121,13 +123,18 @@ std::vector GetNonExistingPortsAfterBreakout( // new mode. absl::Status ValidateBreakoutState( gnmi::gNMI::StubInterface* sut_gnmi_stub, - absl::flat_hash_map& expected_port_info, - std::vector& non_existing_ports_list); + const absl::flat_hash_map& + expected_port_info, + const std::vector& non_existing_ports_list); absl::StatusOr GetPortIndex( const std::string& platform_json_contents, absl::string_view port); -std::string ConstructSupportedBreakoutMode(std::string& num_breakouts, - std::string& breakout_speed); +std::string ConstructSupportedBreakoutMode(absl::string_view num_breakouts, + absl::string_view breakout_speed); + +// IsCopperPort returns whether the port is copper or optic. +absl::StatusOr IsCopperPort(gnmi::gNMI::StubInterface* sut_gnmi_stub, + absl::string_view port); } // namespace pins_test #endif // PINS_TESTS_THINKIT_GNMI_INTERFACE_UTIL_H_ diff --git a/tests/thinkit_gnmi_interface_util_tests.cc b/tests/thinkit_gnmi_interface_util_tests.cc index 42fbec18..0a9baa9f 100644 --- a/tests/thinkit_gnmi_interface_util_tests.cc +++ b/tests/thinkit_gnmi_interface_util_tests.cc @@ -34,6 +34,98 @@ using ::testing::Return; using ::testing::ReturnRefOfCopy; using ::testing::SetArgPointee; +constexpr char get_xcvrd_req_str[] = + R"pb(prefix { origin: "openconfig" } + path { + elem { name: "interfaces" } + elem { + name: "interface" + key { key: "name" value: "Ethernet0" } + } + elem { name: "state" } + elem { name: "transceiver" } + } + type: STATE)pb"; + +constexpr char get_xcvrd_resp_str[] = + R"pb(notification { + timestamp: 1631864194292383538 + prefix { origin: "openconfig" } + update { + path { + elem { name: "interfaces" } + elem { + name: "interface" + key { key: "name" value: "Ethernet0" } + } + elem { name: "state" } + elem { name: "transceiver" } + } + val { + json_ietf_val: "{\"openconfig-platform-transceiver:transceiver\":\"Ethernet0\"}" + } + } + } + )pb"; + +constexpr char cable_len_req_str[] = + R"pb(prefix { origin: "openconfig" } + path { + elem { name: "components" } + elem { + name: "component" + key { key: "name" value: "Ethernet0" } + } + elem { name: "transceiver" } + elem { name: "state" } + elem { name: "openconfig-platform-ext:cable-length" } + } + type: STATE)pb"; + +constexpr char cable_len_resp_copper_str[] = + R"pb(notification { + timestamp: 1631864194292383538 + prefix { origin: "openconfig" } + update { + path { + elem { name: "components" } + elem { + name: "component" + key { key: "name" value: "Ethernet0" } + } + elem { name: "transceiver" } + elem { name: "state" } + elem { name: "openconfig-platform-ext:cable-length" } + } + val { + json_ietf_val: "{\"openconfig-platform-ext:cable-length\":\"10\"}" + } + } + } + )pb"; + +constexpr char cable_len_resp_optic_str[] = + R"pb(notification { + timestamp: 1631864194292383538 + prefix { origin: "openconfig" } + update { + path { + elem { name: "components" } + elem { + name: "component" + key { key: "name" value: "Ethernet0" } + } + elem { name: "transceiver" } + elem { name: "state" } + elem { name: "cable-length" } + } + val { + json_ietf_val: "{\"openconfig-platform-ext:cable-length\":\"0\"}" + } + } + } + )pb"; + class GNMIThinkitInterfaceUtilityTest : public ::testing::Test { protected: void SetUp() override { @@ -630,7 +722,7 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetExpectedPortInfoForBreakoutModeMixedBreakoutModeSuccess) { const std::string port = "Ethernet0"; - absl::string_view breakout_mode = "1x200G+2x100G"; + absl::string_view breakout_mode = "1x200G(4)+2x100G(4)"; auto breakout_info = pins_test::GetExpectedPortInfoForBreakoutMode(port, breakout_mode); @@ -644,7 +736,7 @@ TEST_F( GNMIThinkitInterfaceUtilityTest, TestGetExpectedPortInfoForBreakoutModeAlternatedMixedBreakoutModeSuccess) { const std::string port = "Ethernet0"; - absl::string_view breakout_mode = "2x100G+1x200G"; + absl::string_view breakout_mode = "2x100G(4)+1x200G(4)"; auto breakout_info = pins_test::GetExpectedPortInfoForBreakoutMode(port, breakout_mode); ASSERT_OK(breakout_info.status()); @@ -713,7 +805,7 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetExpectedPortInfoForBreakoutModeInvalidBreakoutModeFailure) { const std::string port = "Ethernet0"; - absl::string_view breakout_mode = "3x200G+2x100G"; + absl::string_view breakout_mode = "3x200G(4)+2x100G(4)"; EXPECT_THAT( pins_test::GetExpectedPortInfoForBreakoutMode(port, breakout_mode), @@ -921,6 +1013,7 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetBreakoutModeConfigFromStringUnchannelizedBreakoutModeSuccess) { const std::string port_index = "1"; + const std::string intf_name = "Ethernet0"; const std::string breakout_mode = "1x400G"; gnmi::SetRequest req, expected_breakout_config; const std::string expected_breakout_config_str = @@ -934,14 +1027,34 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, })pb"; ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( expected_breakout_config_str, &expected_breakout_config)); - ASSERT_OK(pins_test::GetBreakoutModeConfigFromString(req, port_index, - breakout_mode)); + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, + &get_xcvrd_req)); + gnmi::GetResponse get_xcvrd_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, + &get_xcvrd_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(get_xcvrd_resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_optic_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + ASSERT_OK(pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode)); EXPECT_THAT(req, EqualsProto(expected_breakout_config)); } TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetBreakoutModeConfigFromStringChannelizedBreakoutModeSuccess) { const std::string port_index = "1"; + const std::string intf_name = "Ethernet0"; const std::string breakout_mode = "2x200G"; gnmi::SetRequest req, expected_breakout_config; const std::string expected_breakout_config_str = R"pb( @@ -955,15 +1068,35 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, )pb"; ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( expected_breakout_config_str, &expected_breakout_config)); - ASSERT_OK(pins_test::GetBreakoutModeConfigFromString(req, port_index, - breakout_mode)); + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, + &get_xcvrd_req)); + gnmi::GetResponse get_xcvrd_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, + &get_xcvrd_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(get_xcvrd_resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_optic_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + ASSERT_OK(pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode)); EXPECT_THAT(req, EqualsProto(expected_breakout_config)); } TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetBreakoutModeConfigFromStringMixedBreakoutModeSuccess) { const std::string port_index = "1"; - const std::string breakout_mode = "1x200G+2x100G"; + const std::string intf_name = "Ethernet0"; + const std::string breakout_mode = "1x200G(4)+2x100G(4)"; gnmi::SetRequest req, expected_breakout_config; const std::string expected_breakout_config_str = R"pb( prefix { origin: "openconfig" } @@ -976,20 +1109,132 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, )pb"; ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( expected_breakout_config_str, &expected_breakout_config)); - ASSERT_OK(pins_test::GetBreakoutModeConfigFromString(req, port_index, - breakout_mode)); + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, + &get_xcvrd_req)); + gnmi::GetResponse get_xcvrd_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, + &get_xcvrd_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(get_xcvrd_resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_optic_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + ASSERT_OK(pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode)); + EXPECT_THAT(req, EqualsProto(expected_breakout_config)); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, + TestGetBreakoutModeConfigFromStringCopperPortSuccess) { + const std::string port_index = "1"; + const std::string intf_name = "Ethernet0"; + const std::string breakout_mode = "1x200G(4)+2x100G(4)"; + gnmi::SetRequest req, expected_breakout_config; + const std::string expected_breakout_config_str = R"pb( + prefix { origin: "openconfig" } + replace { + path {} + val { + json_ietf_val: "{\n \"openconfig-interfaces:interfaces\": { \"interface\": [ {\n \"config\": {\n \"enabled\": true,\n \"loopback-mode\": false,\n \"mtu\": 9216,\n \"name\": \"Ethernet0\",\n \"type\": \"iana-if-type:ethernetCsmacd\"\n },\n \"name\": \"Ethernet0\",\n \"openconfig-if-ethernet:ethernet\": {\n \"config\": {\n \"port-speed\": \"openconfig-if-ethernet:SPEED_200GB\",\n \"standalone-link-training\": true\n }\n },\n \"subinterfaces\": {\n \"subinterface\":\n [ {\n \"config\": { \"index\": 0 },\n \"index\": 0,\n \"openconfig-if-ip:ipv6\": {\n \"unnumbered\": { \"config\": { \"enabled\": true } }\n }\n }]\n }\n }\n ,{\n \"config\": {\n \"enabled\": true,\n \"loopback-mode\": false,\n \"mtu\": 9216,\n \"name\": \"Ethernet4\",\n \"type\": \"iana-if-type:ethernetCsmacd\"\n },\n \"name\": \"Ethernet4\",\n \"openconfig-if-ethernet:ethernet\": {\n \"config\": {\n \"port-speed\": \"openconfig-if-ethernet:SPEED_100GB\",\n \"standalone-link-training\": true\n }\n },\n \"subinterfaces\": {\n \"subinterface\":\n [ {\n \"config\": { \"index\": 0 },\n \"index\": 0,\n \"openconfig-if-ip:ipv6\": {\n \"unnumbered\": { \"config\": { \"enabled\": true } }\n }\n }]\n }\n }\n ,{\n \"config\": {\n \"enabled\": true,\n \"loopback-mode\": false,\n \"mtu\": 9216,\n \"name\": \"Ethernet6\",\n \"type\": \"iana-if-type:ethernetCsmacd\"\n },\n \"name\": \"Ethernet6\",\n \"openconfig-if-ethernet:ethernet\": {\n \"config\": {\n \"port-speed\": \"openconfig-if-ethernet:SPEED_100GB\",\n \"standalone-link-training\": true\n }\n },\n \"subinterfaces\": {\n \"subinterface\":\n [ {\n \"config\": { \"index\": 0 },\n \"index\": 0,\n \"openconfig-if-ip:ipv6\": {\n \"unnumbered\": { \"config\": { \"enabled\": true } }\n }\n }]\n }\n }\n ] },\n \"openconfig-platform:components\": {\n \"component\":\n [ {\n \"name\": \"1/1\",\n \"config\": { \"name\": \"1/1\" },\n \"port\": {\n \"config\": { \"port-id\": 1 },\n \"breakout-mode\": { \"groups\": { \"group\": [ {\n \"config\": {\n \"breakout-speed\": \"openconfig-if-ethernet:SPEED_200GB\",\n \"index\": 0,\n \"num-breakouts\": 1,\n \"num-physical-channels\": 4\n },\n \"index\": 0\n },{\n \"config\": {\n \"breakout-speed\": \"openconfig-if-ethernet:SPEED_100GB\",\n \"index\": 1,\n \"num-breakouts\": 2,\n \"num-physical-channels\": 2\n },\n \"index\": 1\n } ] } }\n }\n }]\n }\n }" + } + } + )pb"; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + expected_breakout_config_str, &expected_breakout_config)); + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, + &get_xcvrd_req)); + gnmi::GetResponse get_xcvrd_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, + &get_xcvrd_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(get_xcvrd_resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_copper_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + ASSERT_OK(pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode)); EXPECT_THAT(req, EqualsProto(expected_breakout_config)); } TEST_F(GNMIThinkitInterfaceUtilityTest, TestGetBreakoutModeConfigFromStringIntConversionFailure) { const std::string port_index = "1"; + const std::string intf_name = "Ethernet0"; const std::string breakout_mode = "Xx400G"; + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, + &get_xcvrd_req)); + gnmi::GetResponse get_xcvrd_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, + &get_xcvrd_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(get_xcvrd_resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_optic_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); gnmi::SetRequest req; - EXPECT_THAT(pins_test::GetBreakoutModeConfigFromString(req, port_index, - breakout_mode), - StatusIs(absl::StatusCode::kInternal, - HasSubstr("Failed to convert string (X) to integer"))); + EXPECT_THAT( + pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode), + StatusIs(absl::StatusCode::kInternal, + HasSubstr("Failed to convert string (X) to integer"))); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, + TestGetBreakoutModeConfigFromStringIsCopperPortFailure) { + const std::string port_index = "1"; + const std::string intf_name = "Ethernet0"; + const std::string breakout_mode = "Xx400G"; + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest get_xcvrd_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + R"pb(prefix { origin: "openconfig" } + path { + elem { name: "interfaces" } + elem { + name: "interface" + key { key: "name" value: "Ethernet0" } + } + elem { name: "state" } + elem { name: "transceiver" } + } + type: STATE)pb", + &get_xcvrd_req)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(get_xcvrd_req), _)) + .WillOnce(Return(grpc::Status(grpc::StatusCode::DEADLINE_EXCEEDED, ""))); + gnmi::SetRequest req; + EXPECT_THAT( + pins_test::GetBreakoutModeConfigFromString( + req, mock_gnmi_stub_ptr.get(), port_index, intf_name, breakout_mode), + StatusIs(absl::StatusCode::kDeadlineExceeded, + HasSubstr("Failed to get GNMI state path value for port " + "transceiver for port Ethernet0"))); } TEST_F(GNMIThinkitInterfaceUtilityTest, @@ -1497,4 +1742,129 @@ TEST_F(GNMIThinkitInterfaceUtilityTest, StatusIs(absl::StatusCode::kInternal, HasSubstr("Failed to convert string (X) to integer"))); } + +TEST_F(GNMIThinkitInterfaceUtilityTest, TestIsCopperPortSuccessOpticPort) { + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest req; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, &req)); + gnmi::GetResponse resp; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, &resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(req), _)) + .WillOnce(DoAll(SetArgPointee<2>(resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_optic_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + EXPECT_THAT(pins_test::IsCopperPort(mock_gnmi_stub_ptr.get(), "Ethernet0"), + false); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, TestIsCopperPortSuccessCopperPort) { + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest req; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, &req)); + gnmi::GetResponse resp; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, &resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(req), _)) + .WillOnce(DoAll(SetArgPointee<2>(resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + cable_len_resp_copper_str, &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + EXPECT_THAT(pins_test::IsCopperPort(mock_gnmi_stub_ptr.get(), "Ethernet0"), + true); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, TestIsCopperPortTransceiverGetFailure) { + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest req; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, &req)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(req), _)) + .WillOnce(Return(grpc::Status(grpc::StatusCode::DEADLINE_EXCEEDED, ""))); + EXPECT_THAT(pins_test::IsCopperPort(mock_gnmi_stub_ptr.get(), "Ethernet0"), + StatusIs(absl::StatusCode::kDeadlineExceeded, + HasSubstr("Failed to get GNMI state path value for " + "port transceiver for port Ethernet0"))); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, TestIsCopperPortCableLengthGetFailure) { + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest req; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, &req)); + gnmi::GetResponse resp; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, &resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(req), _)) + .WillOnce(DoAll(SetArgPointee<2>(resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce(Return(grpc::Status(grpc::StatusCode::DEADLINE_EXCEEDED, ""))); + EXPECT_THAT(pins_test::IsCopperPort(mock_gnmi_stub_ptr.get(), "Ethernet0"), + StatusIs(absl::StatusCode::kDeadlineExceeded, + HasSubstr("Failed to get GNMI state path value for " + "cable-length for port Ethernet0"))); +} + +TEST_F(GNMIThinkitInterfaceUtilityTest, + TestIsCopperPortFloatConversionFailure) { + auto mock_gnmi_stub_ptr = absl::make_unique(); + gnmi::GetRequest req; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_req_str, &req)); + gnmi::GetResponse resp; + ASSERT_TRUE( + google::protobuf::TextFormat::ParseFromString(get_xcvrd_resp_str, &resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(req), _)) + .WillOnce(DoAll(SetArgPointee<2>(resp), Return(grpc::Status::OK))); + gnmi::GetRequest cable_len_req; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(cable_len_req_str, + &cable_len_req)); + gnmi::GetResponse cable_len_resp; + ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString( + R"pb(notification { + timestamp: 1631864194292383538 + prefix { origin: "openconfig" } + update { + path { + elem { name: "components" } + elem { + name: "component" + key { key: "name" value: "Ethernet0" } + } + elem { name: "transceiver" } + elem { name: "state" } + elem { name: "openconfig-platform-ext:cable-length" } + } + val { + json_ietf_val: "{\"openconfig-platform-ext:cable-length\":\"XYZ\"}" + } + } + } + )pb", + &cable_len_resp)); + EXPECT_CALL(*mock_gnmi_stub_ptr, Get(_, EqualsProto(cable_len_req), _)) + .WillOnce( + DoAll(SetArgPointee<2>(cable_len_resp), Return(grpc::Status::OK))); + EXPECT_THAT(pins_test::IsCopperPort(mock_gnmi_stub_ptr.get(), "Ethernet0"), + StatusIs(absl::StatusCode::kInternal, + HasSubstr("Failed to convert string (XYZ) to float"))); +} } // namespace pins_test