unittest/meta/TestSaiSerialize.cpp (933 lines of code) (raw):

#include "sai_serialize.h" #include "MetaTestSaiInterface.h" #include "Meta.h" #include "sairedis.h" #include "sairediscommon.h" #include <nlohmann/json.hpp> #include <inttypes.h> #include <arpa/inet.h> #include <gtest/gtest.h> #include <memory> using namespace saimeta; using json = nlohmann::json; TEST(SaiSerialize, transfer_attributes) { SWSS_LOG_ENTER(); sai_attribute_t src; sai_attribute_t dst; memset(&src, 0, sizeof(src)); memset(&dst, 0, sizeof(dst)); EXPECT_EQ(SAI_STATUS_SUCCESS, transfer_attributes(SAI_OBJECT_TYPE_SWITCH, 1, &src, &dst, true)); EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_NULL, 1, &src, &dst, true), std::runtime_error); src.id = 0; dst.id = 1; EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_SWITCH, 1, &src, &dst, true), std::runtime_error); for (size_t idx = 0 ; idx < sai_metadata_attr_sorted_by_id_name_count; ++idx) { auto meta = sai_metadata_attr_sorted_by_id_name[idx]; src.id = meta->attrid; dst.id = meta->attrid; EXPECT_EQ(SAI_STATUS_SUCCESS, transfer_attributes(meta->objecttype, 1, &src, &dst, true)); } } TEST(SaiSerialize, sai_serialize_object_meta_key) { sai_object_meta_key_t mk; mk.objecttype = SAI_OBJECT_TYPE_NULL; EXPECT_THROW(sai_serialize_object_meta_key(mk), std::runtime_error); memset(&mk, 0, sizeof(mk)); for (size_t i = 1; i < sai_metadata_enum_sai_object_type_t.valuescount; ++i) { mk.objecttype = (sai_object_type_t)sai_metadata_enum_sai_object_type_t.values[i]; auto s = sai_serialize_object_meta_key(mk); sai_deserialize_object_meta_key(s, mk); } } TEST(SaiSerialize, sai_serialize_port_lane_latch_status_list) { sai_attribute_t attr; memset(&attr, 0, sizeof(attr)); for (size_t idx = 0 ; idx < sai_metadata_attr_sorted_by_id_name_count; ++idx) { auto meta = sai_metadata_attr_sorted_by_id_name[idx]; if(meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_PORT_LANE_LATCH_STATUS_LIST) { attr.id = meta->attrid; if (meta->isaclaction) { attr.value.aclaction.enable = true; } if (meta->isaclfield) { attr.value.aclfield.enable = true; } sai_port_lane_latch_status_t list[1]; list[0].lane = 1; list[0].value.changed=true; list[0].value.current_status=true; attr.value.portlanelatchstatuslist.count=1; attr.value.portlanelatchstatuslist.list = list; auto s = sai_serialize_attr_value(*meta, attr, false); sai_deserialize_attr_value(s, *meta, attr, false); } } } TEST(SaiSerialize, sai_serialize_attr_value) { sai_attribute_t attr; memset(&attr, 0, sizeof(attr)); for (size_t idx = 0 ; idx < sai_metadata_attr_sorted_by_id_name_count; ++idx) { auto meta = sai_metadata_attr_sorted_by_id_name[idx]; switch (meta->attrvaluetype) { // values that currently don't have serialization methods case SAI_ATTR_VALUE_TYPE_TIMESPEC: case SAI_ATTR_VALUE_TYPE_PORT_ERR_STATUS_LIST: case SAI_ATTR_VALUE_TYPE_PORT_EYE_VALUES_LIST: case SAI_ATTR_VALUE_TYPE_FABRIC_PORT_REACHABILITY: case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: case SAI_ATTR_VALUE_TYPE_SEGMENT_LIST: case SAI_ATTR_VALUE_TYPE_TLV_LIST: case SAI_ATTR_VALUE_TYPE_MAP_LIST: case SAI_ATTR_VALUE_TYPE_PORT_FREQUENCY_OFFSET_PPM_LIST: case SAI_ATTR_VALUE_TYPE_PORT_SNR_LIST: case SAI_ATTR_VALUE_TYPE_ACL_CHAIN_LIST: continue; default: break; } attr.id = meta->attrid; if (meta->isaclaction) { attr.value.aclaction.enable = true; } if (meta->isaclfield) { attr.value.aclfield.enable = true; } auto s = sai_serialize_attr_value(*meta, attr, false); sai_deserialize_attr_value(s, *meta, attr, false); sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); } } TEST(SaiSerialize, sai_deserialize_redis_communication_mode) { sai_redis_communication_mode_t value; sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_REDIS_ASYNC_STRING, value); EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_REDIS_ASYNC); sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING, value); EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC); sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_ZMQ_SYNC_STRING, value); EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_ZMQ_SYNC); } TEST(SaiSerialize, sai_deserialize_ingress_priority_group_attr) { auto s = sai_serialize_ingress_priority_group_attr(SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE); EXPECT_EQ(s, "SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"); sai_ingress_priority_group_attr_t attr; sai_deserialize_ingress_priority_group_attr(s, attr); } //TEST(SaiSerialize, char_to_int) //{ // EXPECT_THROW(char_to_int('g'), std::runtime_error); // // EXPECT_EQ(char_to_int('a'), 10); //} TEST(SaiSerialize, transfer_list) { sai_attribute_t src; sai_attribute_t dst; memset(&src, 0, sizeof(src)); memset(&dst, 0, sizeof(dst)); src.id = SAI_PORT_ATTR_HW_LANE_LIST; dst.id = SAI_PORT_ATTR_HW_LANE_LIST; uint32_t list[2] = { 2, 1 }; src.value.u32list.count = 2; src.value.u32list.list = list; dst.value.u32list.count = 2; dst.value.u32list.list = nullptr; EXPECT_EQ(SAI_STATUS_FAILURE, transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false)); src.value.u32list.count = 1; src.value.u32list.list = nullptr; dst.value.u32list.count = 1; dst.value.u32list.list = list; EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false), std::runtime_error); src.value.u32list.count = 2; src.value.u32list.list = list; dst.value.u32list.count = 1; dst.value.u32list.list = list; EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false)); } TEST(SaiSerialize, sai_deserialize_ip_prefix) { sai_ip_prefix_t p; memset(&p, 0, sizeof(p)); p.addr_family = SAI_IP_ADDR_FAMILY_IPV6; p.addr.ip6[0] = 0x11; p.mask.ip6[0] = 0xFF; p.mask.ip6[1] = 0xF0; auto s = sai_serialize_ip_prefix(p); EXPECT_EQ(s, "1100::/12"); sai_deserialize_ip_prefix(s, p); EXPECT_THROW(sai_deserialize_ip_prefix("a/0/c", p), std::runtime_error); EXPECT_THROW(sai_deserialize_ip_prefix("12x/0", p), std::runtime_error); p.addr_family = SAI_IP_ADDR_FAMILY_IPV4; sai_deserialize_ip_prefix("127.0.0.1/8", p); } TEST(SaiSerialize, sai_serialize_ip_prefix) { sai_ip_prefix_t p; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" p.addr_family = (sai_ip_addr_family_t)7; #pragma GCC diagnostic pop EXPECT_THROW(sai_serialize_ip_prefix(p), std::runtime_error); } TEST(SaiSerialize, sai_deserialize_ip_address) { sai_ip_address_t a; EXPECT_THROW(sai_deserialize_ip_address("123", a), std::runtime_error); } TEST(SaiSerialize, sai_deserialize_ipv4) { sai_ip4_t a; EXPECT_THROW(sai_deserialize_ipv4("123", a), std::runtime_error); } TEST(SaiSerialize, sai_deserialize_ipv6) { sai_ip6_t a; EXPECT_THROW(sai_deserialize_ipv6("123", a), std::runtime_error); } TEST(SaiSerialize, sai_deserialize_chardata) { sai_attribute_t a; EXPECT_THROW(sai_deserialize_chardata(std::string("123456789012345678901234567890123"), a.value.chardata), std::runtime_error); EXPECT_THROW(sai_deserialize_chardata(std::string("abc\\"), a.value.chardata), std::runtime_error); EXPECT_THROW(sai_deserialize_chardata(std::string("abc\\x"), a.value.chardata), std::runtime_error); EXPECT_THROW(sai_deserialize_chardata(std::string("a\\\\bc\\x1"), a.value.chardata), std::runtime_error); EXPECT_THROW(sai_deserialize_chardata(std::string("a\\\\bc\\xzg"), a.value.chardata), std::runtime_error); sai_deserialize_chardata(std::string("a\\\\\\x22"), a.value.chardata); } TEST(SaiSerialize, sai_serialize_chardata) { sai_attribute_t a; a.value.chardata[0] = 'a'; a.value.chardata[1] = '\\'; a.value.chardata[2] = 'b'; a.value.chardata[3] = 7; a.value.chardata[4] = 0; auto s = sai_serialize_chardata(a.value.chardata); EXPECT_EQ(s, "a\\\\b\\x07"); } TEST(SaiSerialize, sai_serialize_api) { EXPECT_EQ(sai_serialize_api(SAI_API_VLAN), "SAI_API_VLAN"); } TEST(SaiSerialize, sai_serialize_vlan_id) { EXPECT_EQ(sai_serialize_vlan_id(123), "123"); } TEST(SaiSerialize, sai_deserialize_vlan_id) { sai_vlan_id_t vlan; sai_deserialize_vlan_id("123", vlan); } TEST(SaiSerialize, sai_serialize_port_stat) { EXPECT_EQ(sai_serialize_port_stat(SAI_PORT_STAT_IF_IN_OCTETS),"SAI_PORT_STAT_IF_IN_OCTETS"); } TEST(SaiSerialize, sai_serialize_switch_stat) { EXPECT_EQ(sai_serialize_switch_stat(SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS), "SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS"); } TEST(SaiSerialize, sai_serialize_port_pool_stat) { EXPECT_EQ(sai_serialize_port_pool_stat(SAI_PORT_POOL_STAT_IF_OCTETS), "SAI_PORT_POOL_STAT_IF_OCTETS"); } TEST(SaiSerialize, sai_serialize_queue_stat) { EXPECT_EQ(sai_serialize_queue_stat(SAI_QUEUE_STAT_PACKETS), "SAI_QUEUE_STAT_PACKETS"); } TEST(SaiSerialize, sai_serialize_router_interface_stat) { EXPECT_EQ(sai_serialize_router_interface_stat(SAI_ROUTER_INTERFACE_STAT_IN_OCTETS), "SAI_ROUTER_INTERFACE_STAT_IN_OCTETS"); } TEST(SaiSerialize, sai_serialize_ingress_priority_group_stat) { EXPECT_EQ(sai_serialize_ingress_priority_group_stat(SAI_INGRESS_PRIORITY_GROUP_STAT_PACKETS), "SAI_INGRESS_PRIORITY_GROUP_STAT_PACKETS"); } TEST(SaiSerialize, sai_serialize_buffer_pool_stat) { EXPECT_EQ(sai_serialize_buffer_pool_stat(SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES), "SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES"); } TEST(SaiSerialize, sai_serialize_tunnel_stat) { EXPECT_EQ(sai_serialize_tunnel_stat(SAI_TUNNEL_STAT_IN_OCTETS), "SAI_TUNNEL_STAT_IN_OCTETS"); } TEST(SaiSerialize, sai_serialize_counter_stat) { EXPECT_EQ(sai_serialize_counter_stat(SAI_COUNTER_STAT_PACKETS), "SAI_COUNTER_STAT_PACKETS"); } TEST(SaiSerialize, sai_serialize_macsec_sa_stat) { EXPECT_EQ(sai_serialize_macsec_sa_stat(SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED), "SAI_MACSEC_SA_STAT_OCTETS_ENCRYPTED"); } TEST(SaiSerialize, sai_serialize_macsec_flow_stat) { EXPECT_EQ(sai_serialize_macsec_flow_stat(SAI_MACSEC_FLOW_STAT_OTHER_ERR), "SAI_MACSEC_FLOW_STAT_OTHER_ERR"); } TEST(SaiSerialize, sai_serialize_queue_attr) { EXPECT_EQ(sai_serialize_queue_attr(SAI_QUEUE_ATTR_TYPE), "SAI_QUEUE_ATTR_TYPE"); } TEST(SaiSerialize, sai_serialize_macsec_sa_attr) { EXPECT_EQ(sai_serialize_macsec_sa_attr(SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION), "SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION"); } TEST(SaiSerialize, sai_serialize_ingress_drop_reason) { EXPECT_EQ(sai_serialize_ingress_drop_reason(SAI_IN_DROP_REASON_L2_ANY), "SAI_IN_DROP_REASON_L2_ANY"); } TEST(SaiSerialize, sai_serialize_egress_drop_reason) { EXPECT_EQ(sai_serialize_egress_drop_reason(SAI_OUT_DROP_REASON_L2_ANY), "SAI_OUT_DROP_REASON_L2_ANY"); } TEST(SaiSerialize, sai_serialize_switch_shutdown_request) { EXPECT_EQ(sai_serialize_switch_shutdown_request(0x1), "{\"switch_id\":\"oid:0x1\"}"); } TEST(SaiSerialize, sai_serialize_oid_list) { sai_object_list_t list; list.count = 2; list.list = nullptr; EXPECT_EQ(sai_serialize_oid_list(list, true), "2"); EXPECT_EQ(sai_serialize_oid_list(list, false), "2:null"); } TEST(SaiSerialize, sai_serialize_hex_binary) { EXPECT_EQ(sai_serialize_hex_binary(nullptr, 0), ""); uint8_t buf[1]; EXPECT_EQ(sai_serialize_hex_binary(buf, 0), ""); } TEST(SaiSerialize, sai_serialize_system_port_config_list) { sai_system_port_config_t pc; memset(&pc, 0, sizeof(pc)); sai_system_port_config_list_t list; list.count = 1; list.list = &pc; sai_attr_metadata_t *meta = nullptr; sai_serialize_system_port_config_list(*meta, list, false); } TEST(SaiSerialize, sai_deserialize_system_port_config_list) { sai_system_port_config_t pc; memset(&pc, 0, sizeof(pc)); sai_system_port_config_list_t list; list.count = 1; list.list = &pc; sai_attr_metadata_t *meta = nullptr; auto s = sai_serialize_system_port_config_list(*meta, list, false); sai_deserialize_system_port_config_list(s, list, false); } TEST(SaiSerialize, sai_serialize_port_oper_status) { EXPECT_EQ(sai_serialize_port_oper_status(SAI_PORT_OPER_STATUS_UP), "SAI_PORT_OPER_STATUS_UP"); } TEST(SaiSerialize, sai_serialize_port_host_tx_ready) { EXPECT_EQ(sai_serialize_port_host_tx_ready(SAI_PORT_HOST_TX_READY_STATUS_READY), "SAI_PORT_HOST_TX_READY_STATUS_READY"); } TEST(SaiSerialize, sai_serialize_queue_deadlock_event) { EXPECT_EQ(sai_serialize_queue_deadlock_event(SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED), "SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED"); } TEST(SaiSerialize, sai_serialize_fdb_event_ntf) { EXPECT_THROW(sai_serialize_fdb_event_ntf(1, nullptr), std::runtime_error); } TEST(SaiSerialize, sai_serialize_nat_event_ntf) { EXPECT_THROW(sai_serialize_nat_event_ntf(1, nullptr), std::runtime_error); } TEST(SaiSerialize, sai_serialize_port_oper_status_ntf) { sai_port_oper_status_notification_t ntf; memset(&ntf, 0, sizeof(ntf)); sai_serialize_port_oper_status_ntf(1, &ntf); EXPECT_THROW(sai_serialize_port_oper_status_ntf(1, nullptr), std::runtime_error); } TEST(SaiSerialize, sai_serialize_queue_deadlock_ntf) { sai_queue_deadlock_notification_data_t ntf; memset(&ntf, 0, sizeof(ntf)); sai_serialize_queue_deadlock_ntf(1, &ntf); EXPECT_THROW(sai_serialize_queue_deadlock_ntf(1, nullptr), std::runtime_error); } TEST(SaiSerialize, sai_serialize) { sai_redis_notify_syncd_t value = SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC; EXPECT_EQ(sai_serialize(value), SYNCD_INSPECT_ASIC); } TEST(SaiSerialize, sai_serialize_redis_communication_mode) { EXPECT_EQ(sai_serialize_redis_communication_mode(SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC), REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING); } TEST(SaiSerialize, sai_serialize_redis_port_attr_id) { for (const auto& attr : {SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGORITHM, SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG}) { sai_redis_port_attr_t deserialized_attr; sai_deserialize_redis_port_attr_id( sai_serialize_redis_port_attr_id(attr), deserialized_attr); EXPECT_EQ(deserialized_attr, attr); } // Undefined enum. int index = 1000; std::string serialized_attr = sai_serialize_redis_port_attr_id( static_cast<sai_redis_port_attr_t>(SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG + index)); EXPECT_EQ(serialized_attr, std::to_string(SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG + index)); sai_redis_port_attr_t deserialized_attr; sai_deserialize_redis_port_attr_id(serialized_attr, deserialized_attr); EXPECT_EQ(deserialized_attr, SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG + index); } TEST(SaiSerialize, sai_serialize_redis_link_event_damping_algorithm) { for (const auto& algo : {SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_DISABLED, SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_AIED}) { sai_redis_link_event_damping_algorithm_t deserialized_algo; sai_deserialize_redis_link_event_damping_algorithm( sai_serialize_redis_link_event_damping_algorithm(algo), deserialized_algo); EXPECT_EQ(deserialized_algo, algo); } // Undefined enum. int index = 1000; std::string serialized_attr = sai_serialize_redis_link_event_damping_algorithm( static_cast<sai_redis_link_event_damping_algorithm_t>(SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_AIED + index)); EXPECT_EQ(serialized_attr, std::to_string(SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_AIED + index)); sai_redis_link_event_damping_algorithm_t deserialized_attr; sai_deserialize_redis_link_event_damping_algorithm(serialized_attr, deserialized_attr); EXPECT_EQ(deserialized_attr, SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_AIED + index); } TEST(SaiSerialize, sai_serialize_redis_link_event_damping_aied_config) { SWSS_LOG_ENTER(); sai_redis_link_event_damping_algo_aied_config_t config = { .max_suppress_time = 500, .suppress_threshold = 2500, .reuse_threshold = 1000, .decay_half_life = 100, .flap_penalty = 100}; std::string expected = "{\"max_suppress_time\":\"500\",\"suppress_threshold\":\"2500\",\"reuse_threshold\":\"1000\",\"decay_half_life\":\"100\",\"flap_penalty\":\"100\"}"; std::string serialized_config = sai_serialize_redis_link_event_damping_aied_config(config); EXPECT_EQ(json::parse(serialized_config), json::parse(expected)); sai_redis_link_event_damping_algo_aied_config_t deserialized_config; sai_deserialize_redis_link_event_damping_aied_config(serialized_config, deserialized_config); EXPECT_EQ(deserialized_config.max_suppress_time, config.max_suppress_time); EXPECT_EQ(deserialized_config.suppress_threshold, config.suppress_threshold); EXPECT_EQ(deserialized_config.reuse_threshold, config.reuse_threshold); EXPECT_EQ(deserialized_config.decay_half_life, config.decay_half_life); EXPECT_EQ(deserialized_config.flap_penalty, config.flap_penalty); } TEST(SaiSerialize, sai_deserialize_queue_attr) { sai_queue_attr_t attr = SAI_QUEUE_ATTR_PORT; sai_deserialize_queue_attr("SAI_QUEUE_ATTR_TYPE", attr); EXPECT_EQ(attr, SAI_QUEUE_ATTR_TYPE); } TEST(SaiSerialize, sai_deserialize_macsec_sa_attr) { sai_macsec_sa_attr_t attr = SAI_MACSEC_SA_ATTR_SC_ID; sai_deserialize_macsec_sa_attr("SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION", attr); EXPECT_EQ(attr, SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION); } TEST(SaiSerialize, sai_deserialize) { sai_redis_notify_syncd_t value = SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW; sai_deserialize("SYNCD_INSPECT_ASIC", value); EXPECT_EQ(value, SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC); } // LEGACY TESTS TEST(SaiSerialize, serialize_bool) { SWSS_LOG_ENTER(); sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; // test bool attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; attr.value.booldata = true; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); EXPECT_EQ(sai_serialize_attr_value(*meta, attr), "true"); attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; attr.value.booldata = false; EXPECT_EQ(sai_serialize_attr_value(*meta, attr), "false"); // deserialize attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; sai_deserialize_attr_value("true", *meta, attr); EXPECT_EQ(true, attr.value.booldata); sai_deserialize_attr_value("false", *meta, attr); EXPECT_EQ(false, attr.value.booldata); EXPECT_THROW(sai_deserialize_attr_value("xx", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_chardata) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; memset(attr.value.chardata, 0, 32); attr.id = SAI_HOSTIF_ATTR_NAME; memcpy(attr.value.chardata, "foo", sizeof("foo")); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "foo"); attr.id = SAI_HOSTIF_ATTR_NAME; memcpy(attr.value.chardata, "f\\oo\x12", sizeof("f\\oo\x12")); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "f\\\\oo\\x12"); attr.id = SAI_HOSTIF_ATTR_NAME; memcpy(attr.value.chardata, "\x80\xff", sizeof("\x80\xff")); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "\\x80\\xFF"); // deserialize sai_deserialize_attr_value("f\\\\oo\\x12", *meta, attr); SWSS_LOG_NOTICE("des: %s", attr.value.chardata); EXPECT_EQ(0, strcmp(attr.value.chardata, "f\\oo\x12")); sai_deserialize_attr_value("foo", *meta, attr); EXPECT_EQ(0, strcmp(attr.value.chardata, "foo")); EXPECT_THROW(sai_deserialize_attr_value("\\x2g", *meta, attr), std::runtime_error); EXPECT_THROW(sai_deserialize_attr_value("\\x2", *meta, attr), std::runtime_error); EXPECT_THROW(sai_deserialize_attr_value("\\s45", *meta, attr), std::runtime_error); EXPECT_THROW(sai_deserialize_attr_value("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_uint64) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; attr.value.u64 = 42; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "42"); attr.value.u64 = 0x87654321aabbccdd; attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); char buf[32]; sprintf(buf, "%" PRIu64, attr.value.u64); EXPECT_EQ(s, std::string(buf)); // deserialize sai_deserialize_attr_value("12345", *meta, attr); EXPECT_EQ(12345, attr.value.u64); EXPECT_THROW(sai_deserialize_attr_value("22345235345345345435", *meta, attr), std::runtime_error); EXPECT_THROW(sai_deserialize_attr_value("2a", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_enum) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; attr.value.s32 = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD"); attr.value.s32 = -1; attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "-1"); attr.value.s32 = 100; attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "100"); // deserialize sai_deserialize_attr_value("12345", *meta, attr); EXPECT_EQ(12345, attr.value.s32); sai_deserialize_attr_value("-1", *meta, attr); EXPECT_EQ(-1, attr.value.s32); sai_deserialize_attr_value("SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD", *meta, attr); EXPECT_EQ(SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD, attr.value.s32); EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_mac) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; memcpy(attr.value.mac, "\x01\x22\x33\xaa\xbb\xcc", 6); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "01:22:33:AA:BB:CC"); // deserialize sai_deserialize_attr_value("ff:ee:dd:33:44:55", *meta, attr); EXPECT_EQ(0, memcmp("\xff\xee\xdd\x33\x44\x55", attr.value.mac, 6)); EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_ip_address) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; attr.value.ipaddr.addr.ip4 = htonl(0x0a000015); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "10.0.0.21"); attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; uint16_t ip6[] = { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0xaaaa, 0xbbbb }; memcpy(attr.value.ipaddr.addr.ip6, ip6, 16); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "1111:2222:3333:4444:5555:6666:aaaa:bbbb"); uint16_t ip6a[] = { 0x0100, 0 ,0 ,0 ,0 ,0 ,0 ,0xff00 }; memcpy(attr.value.ipaddr.addr.ip6, ip6a, 16); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "1::ff"); uint16_t ip6b[] = { 0, 0 ,0 ,0 ,0 ,0 ,0 ,0x100 }; memcpy(attr.value.ipaddr.addr.ip6, ip6b, 16); meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "::1"); int k = 100; attr.value.ipaddr.addr_family = (sai_ip_addr_family_t)k; EXPECT_THROW(sai_serialize_attr_value(*meta, attr), std::runtime_error); // deserialize sai_deserialize_attr_value("10.0.0.23", *meta, attr); EXPECT_EQ(attr.value.ipaddr.addr.ip4, htonl(0x0a000017)); EXPECT_EQ(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV4); sai_deserialize_attr_value("1::ff", *meta, attr); EXPECT_EQ(0, memcmp(attr.value.ipaddr.addr.ip6, ip6a, 16)); EXPECT_EQ(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV6); EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_uint32_list) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED; //SAI_PORT_ATTR_SUPPORTED_HALF_DUPLEX_SPEED; uint32_t list[] = {1,2,3,4,5,6,7}; attr.value.u32list.count = 7; attr.value.u32list.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "7:null"); attr.value.u32list.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "7:1,2,3,4,5,6,7"); attr.value.u32list.count = 0; attr.value.u32list.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); attr.value.u32list.count = 0; attr.value.u32list.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); memset(&attr, 0, sizeof(attr)); sai_deserialize_attr_value("7:1,2,3,4,5,6,7", *meta, attr, false); EXPECT_EQ(attr.value.u32list.count, 7); EXPECT_EQ(attr.value.u32list.list[0], 1); EXPECT_EQ(attr.value.u32list.list[1], 2); EXPECT_EQ(attr.value.u32list.list[2], 3); EXPECT_EQ(attr.value.u32list.list[3], 4); } TEST(SaiSerialize, serialize_enum_list) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; int32_t list[] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID, 77 }; attr.value.s32list.count = 4; attr.value.s32list.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "4:null"); attr.value.s32list.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); s = sai_serialize_attr_value(*meta, attr); // or for enum: 4:SAI_NATIVE_HASH_FIELD[SRC_IP,DST_IP,VLAN_ID,77] EXPECT_EQ(s, "4:SAI_NATIVE_HASH_FIELD_SRC_IP,SAI_NATIVE_HASH_FIELD_DST_IP,SAI_NATIVE_HASH_FIELD_VLAN_ID,77"); attr.value.s32list.count = 0; attr.value.s32list.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); attr.value.s32list.count = 0; attr.value.s32list.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); } TEST(SaiSerialize, serialize_oid) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; attr.value.oid = 0x1234567890abcdef; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "oid:0x1234567890abcdef"); // deserialize sai_deserialize_attr_value("oid:0x1234567890abcdef", *meta, attr); EXPECT_EQ(0x1234567890abcdef, attr.value.oid); EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); } TEST(SaiSerialize, serialize_oid_list) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_SWITCH_ATTR_PORT_LIST; sai_object_id_t list[] = { 1,0x42, 0x77 }; attr.value.objlist.count = 3; attr.value.objlist.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "3:null"); attr.value.objlist.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); // or: 4:[ROUTE:0x1,PORT:0x3,oid:0x77] if we have query function EXPECT_EQ(s, "3:oid:0x1,oid:0x42,oid:0x77"); attr.value.objlist.count = 0; attr.value.objlist.list = list; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); attr.value.objlist.count = 0; attr.value.objlist.list = NULL; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "0:null"); memset(&attr, 0, sizeof(attr)); // deserialize sai_deserialize_attr_value("3:oid:0x1,oid:0x42,oid:0x77", *meta, attr, false); EXPECT_EQ(attr.value.objlist.count, 3); EXPECT_EQ(attr.value.objlist.list[0], 0x1); EXPECT_EQ(attr.value.objlist.list[1], 0x42); EXPECT_EQ(attr.value.objlist.list[2], 0x77); } TEST(SaiSerialize, serialize_acl_action) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT; attr.value.aclaction.enable = true; attr.value.aclaction.parameter.oid = (sai_object_id_t)2; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "oid:0x2"); attr.value.aclaction.enable = false; attr.value.aclaction.parameter.oid = (sai_object_id_t)2; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "disabled"); attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; attr.value.aclaction.enable = true; attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_TRAP; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "SAI_PACKET_ACTION_TRAP"); attr.value.aclaction.enable = true; attr.value.aclaction.parameter.s32 = 77; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); s = sai_serialize_attr_value(*meta, attr); EXPECT_EQ(s, "77"); } TEST(SaiSerialize, serialize_qos_map) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST; sai_qos_map_t qm = { .key = { .tc = 1, .dscp = 2, .dot1p = 3, .prio = 4, .pg = 5, .queue_index = 6, .color = SAI_PACKET_COLOR_RED, .mpls_exp = 0, .fc = 2 }, .value = { .tc = 11, .dscp = 22, .dot1p = 33, .prio = 44, .pg = 55, .queue_index = 66, .color = SAI_PACKET_COLOR_GREEN, .mpls_exp = 0, .fc = 2 } }; attr.value.qosmap.count = 1; attr.value.qosmap.list = &qm; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_QOS_MAP, attr.id); s = sai_serialize_attr_value(*meta, attr); std::string ret = "{\"count\":1,\"list\":[{\"key\":{\"color\":\"SAI_PACKET_COLOR_RED\",\"dot1p\":3,\"dscp\":2,\"fc\":2,\"mpls_exp\":0,\"pg\":5,\"prio\":4,\"qidx\":6,\"tc\":1},\"value\":{\"color\":\"SAI_PACKET_COLOR_GREEN\",\"dot1p\":33,\"dscp\":22,\"fc\":2,\"mpls_exp\":0,\"pg\":55,\"prio\":44,\"qidx\":66,\"tc\":11}}]}"; EXPECT_EQ(s, ret); s = sai_serialize_attr_value(*meta, attr, true); std::string ret2 = "{\"count\":1,\"list\":null}"; EXPECT_EQ(s, ret2); // deserialize memset(&attr, 0, sizeof(attr)); sai_deserialize_attr_value(ret, *meta, attr); EXPECT_EQ(attr.value.qosmap.count, 1); auto &l = attr.value.qosmap.list[0]; EXPECT_EQ(l.key.tc, 1); EXPECT_EQ(l.key.dscp, 2); EXPECT_EQ(l.key.dot1p, 3); EXPECT_EQ(l.key.prio, 4); EXPECT_EQ(l.key.pg, 5); EXPECT_EQ(l.key.queue_index, 6); EXPECT_EQ(l.key.color, SAI_PACKET_COLOR_RED); EXPECT_EQ(l.key.mpls_exp, 0); EXPECT_EQ(l.key.fc, 2); EXPECT_EQ(l.value.tc, 11); EXPECT_EQ(l.value.dscp, 22); EXPECT_EQ(l.value.dot1p, 33); EXPECT_EQ(l.value.prio, 44); EXPECT_EQ(l.value.pg, 55); EXPECT_EQ(l.value.queue_index, 66); EXPECT_EQ(l.value.color, SAI_PACKET_COLOR_GREEN); EXPECT_EQ(l.value.mpls_exp, 0); EXPECT_EQ(l.value.fc, 2); } TEST(SaiSerialize, serialize_map) { sai_attribute_t attr; const sai_attr_metadata_t* meta; std::string s; attr.id = SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST; sai_map_t map = { .key = 1, .value = 11 }; attr.value.maplist.count = 1; attr.value.maplist.list = &map; meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP, attr.id); s = sai_serialize_attr_value(*meta, attr); std::string ret = "{\"count\":1,\"list\":[{\"key\":1,\"value\":11}]}"; EXPECT_EQ(s, ret); s = sai_serialize_attr_value(*meta, attr, true); std::string ret2 = "{\"count\":1,\"list\":null}"; EXPECT_EQ(s, ret2); // deserialize memset(&attr, 0, sizeof(attr)); sai_deserialize_attr_value(ret, *meta, attr); EXPECT_EQ(attr.value.maplist.count, 1); auto &l = attr.value.maplist.list[0]; EXPECT_EQ(l.key, 1); EXPECT_EQ(l.value, 11); } template<typename T> static void deserialize_number( _In_ const std::string& s, _Out_ T& number, _In_ bool hex = false) { SWSS_LOG_ENTER(); errno = 0; char *endptr = NULL; number = (T)strtoull(s.c_str(), &endptr, hex ? 16 : 10); if (errno != 0 || endptr != s.c_str() + s.length()) { SWSS_LOG_THROW("invalid number %s", s.c_str()); } } template <typename T> static std::string serialize_number( _In_ const T& number, _In_ bool hex = false) { SWSS_LOG_ENTER(); if (hex) { char buf[32]; snprintf(buf, sizeof(buf), "0x%" PRIx64, (uint64_t)number); return buf; } return std::to_string(number); } TEST(SaiSerialize, serialize_number) { SWSS_LOG_ENTER(); int64_t sp = 0x12345678; int64_t sn = -0x12345678; int64_t u = 0x12345678; auto ssp = serialize_number(sp); auto ssn = serialize_number(sn); auto su = serialize_number(u); EXPECT_EQ(ssp, std::to_string(sp)); EXPECT_EQ(ssn, std::to_string(sn)); EXPECT_EQ(su, std::to_string(u)); auto shsp = serialize_number(sp, true); auto shsn = serialize_number(sn, true); auto shu = serialize_number(u, true); EXPECT_EQ(shsp, "0x12345678"); EXPECT_EQ(shsn, "0xffffffffedcba988"); EXPECT_EQ(shu, "0x12345678"); sp = 0; sn = 0; u = 0; deserialize_number(ssp, sp); deserialize_number(ssn, sn); deserialize_number(su, u); EXPECT_EQ(sp, 0x12345678); EXPECT_EQ(sn, -0x12345678); EXPECT_EQ(u, 0x12345678); deserialize_number(shsp, sp, true); deserialize_number(shsn, sn, true); deserialize_number(shu, u, true); EXPECT_EQ(sp, 0x12345678); EXPECT_EQ(sn, -0x12345678); EXPECT_EQ(u, 0x12345678); } TEST(SaiSerialize, serialize_stat_capability_list) { SWSS_LOG_ENTER(); extern const sai_enum_metadata_t sai_metadata_enum_sai_stats_mode_t; sai_stat_capability_list_t queue_stats_capability; sai_stat_capability_t stat_initializer; stat_initializer.stat_enum = 0; stat_initializer.stat_modes = 0; std::vector<sai_stat_capability_t> qstat_cap_list(2, stat_initializer); queue_stats_capability.count = 2; queue_stats_capability.list = qstat_cap_list.data(); queue_stats_capability.list[0].stat_enum = SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS; queue_stats_capability.list[0].stat_modes = SAI_STATS_MODE_READ; queue_stats_capability.list[1].stat_enum = SAI_QUEUE_STAT_PACKETS; queue_stats_capability.list[1].stat_modes = SAI_STATS_MODE_READ; std::string capab_count = sai_serialize_stats_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, true); std::string capab_str = sai_serialize_stats_capability_list(queue_stats_capability, &sai_metadata_enum_sai_stats_mode_t, false); std::string exp_count_str = "{\"count\":2,\"list\":null}"; EXPECT_EQ(capab_count, exp_count_str); std::string exp_capab_str = "{\"count\":2,\"list\":[{\"stat_enum\":\"34\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]},{\"stat_enum\":\"0\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}"; EXPECT_EQ(capab_str, exp_capab_str); std::vector<std::string> vec_stat_enum; std::vector<std::string> vec_stat_modes; for (uint32_t it = 0; it < queue_stats_capability.count; it++) { vec_stat_enum.push_back(std::to_string(queue_stats_capability.list[it].stat_enum)); vec_stat_modes.push_back(std::to_string(queue_stats_capability.list[it].stat_modes)); } std::ostringstream join_stat_enum; std::copy(vec_stat_enum.begin(), vec_stat_enum.end(), std::ostream_iterator<std::string>(join_stat_enum, ",")); auto strCapEnum = join_stat_enum.str(); std::ostringstream join_stat_modes; std::copy(vec_stat_modes.begin(), vec_stat_modes.end(), std::ostream_iterator<std::string>(join_stat_modes, ",")); auto strCapModes = join_stat_modes.str(); sai_stat_capability_list_t stats_capability; std::vector<sai_stat_capability_t> stat_cap_list(queue_stats_capability.count, stat_initializer); stats_capability.count = queue_stats_capability.count; stats_capability.list = stat_cap_list.data(); // deserialize EXPECT_THROW(sai_deserialize_stats_capability_list(NULL, strCapEnum, strCapModes), std::runtime_error); sai_deserialize_stats_capability_list(&stats_capability, strCapEnum, strCapModes); EXPECT_EQ(stats_capability.count, queue_stats_capability.count); EXPECT_EQ(stats_capability.list[0].stat_modes, SAI_STATS_MODE_READ); EXPECT_EQ(stats_capability.list[1].stat_modes, SAI_STATS_MODE_READ); int is_expected_enum = false; if ((stats_capability.list[0].stat_enum == SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS)||(stats_capability.list[1].stat_enum == SAI_QUEUE_STAT_PACKETS)) { is_expected_enum = true; } if ((stats_capability.list[1].stat_enum == SAI_QUEUE_STAT_WRED_ECN_MARKED_PACKETS)||(stats_capability.list[0].stat_enum == SAI_QUEUE_STAT_PACKETS)) { is_expected_enum = true; } EXPECT_EQ(is_expected_enum, true); }