lib/tests.cpp (772 lines of code) (raw):
extern "C" {
#include "saimetadata.h"
}
#include "ContextConfigContainer.h"
#include "swss/logger.h"
#include "swss/table.h"
#include "swss/tokenize.h"
#include "Recorder.h"
#include "meta/sai_serialize.h"
#include "meta/SaiAttributeList.h"
#include "meta/Globals.h"
#include <unistd.h>
#include <iostream>
#include <chrono>
#include <vector>
#define ASSERT_EQ(a,b) if ((a) != (b)) { SWSS_LOG_THROW("ASSERT EQ FAILED: " #a " != " #b); }
using namespace saimeta;
using namespace sairedis;
const std::string SairedisRecFilename = "sairedis.rec";
sai_object_type_t sai_object_type_query(
_In_ sai_object_id_t objectId)
{
SWSS_LOG_ENTER();
return SAI_OBJECT_TYPE_NULL;
}
sai_object_id_t sai_switch_id_query(
_In_ sai_object_id_t objectId)
{
SWSS_LOG_ENTER();
return SAI_NULL_OBJECT_ID;
}
sai_route_entry_t get_route_entry()
{
SWSS_LOG_ENTER();
sai_route_entry_t route_entry = { };
route_entry.vr_id = 0x123456789abcdef;
route_entry.switch_id = 0x123456789abcdef;
route_entry.destination.addr.ip4 = 0x12345678;
route_entry.destination.mask.ip4 = 0xffffffff;
return route_entry;
}
std::string serialize_route_entry()
{
SWSS_LOG_ENTER();
static auto route_entry = get_route_entry();
return sai_serialize_object_type(SAI_OBJECT_TYPE_ROUTE_ENTRY) + ":" +
sai_serialize_route_entry(route_entry);
}
std::string serialize_route_entry2()
{
SWSS_LOG_ENTER();
static auto route_entry = get_route_entry();
char buffer[1000];
int n = sai_serialize_object_type(buffer, SAI_OBJECT_TYPE_ROUTE_ENTRY);
buffer[n] = ':';
sai_serialize_route_entry(buffer+n+1, &route_entry);
return std::string(buffer);
}
std::string serialize_vlan()
{
SWSS_LOG_ENTER();
sai_object_id_t oid = 0x123456789abcdef;
return sai_serialize_object_type(SAI_OBJECT_TYPE_VLAN) + ":" +
sai_serialize_object_id(oid);
}
void test_serialize_remove_route_entry(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_route_entry() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_route_entry();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
void test_deserialize_route_entry_meta(int n)
{
SWSS_LOG_ENTER();
// meta key 123ms/10k
auto s = serialize_route_entry();
// auto s = sai_serialize_route_entry(get_route_entry());
std::cout << s << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
sai_object_meta_key_t mk;
sai_deserialize_object_meta_key(s, mk);
//sai_route_entry_t route_entry;
//sai_deserialize_route_entry(s, route_entry);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
void test_deserialize_route_entry(int n)
{
SWSS_LOG_ENTER();
// 7.2 ms
// 8.9 ms with try/catch
// 13ms for entire object meta key
char buffer[1000];
sai_route_entry_t route_entry = get_route_entry();
sai_serialize_route_entry(buffer, &route_entry);
auto s = std::string(buffer);
std::cout << s << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
sai_deserialize_route_entry(s.c_str(), &route_entry);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
void test_serialize_remove_oid(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_vlan() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_vlan();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
sai_fdb_entry_t get_fdb_entry()
{
SWSS_LOG_ENTER();
std::string str = "{\"bvid\":\"oid:0x123456789abcdef\",\"mac\":\"52:54:00:79:16:93\",\"switch_id\":\"oid:0x123456789abcdef\"}";
sai_fdb_entry_t fdb_entry;
sai_deserialize_fdb_entry(str, fdb_entry);
return fdb_entry;
}
std::string serialize_fdb_entry()
{
SWSS_LOG_ENTER();
static auto fdb_entry = get_fdb_entry();
return sai_serialize_object_type(SAI_OBJECT_TYPE_FDB_ENTRY) + ":" +
sai_serialize_fdb_entry(fdb_entry);
}
void test_serialize_remove_fdb_entry(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_fdb_entry() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_fdb_entry();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
std::string serialize_bulk_vlan(int per)
{
SWSS_LOG_ENTER();
sai_object_id_t oid = 0x123456789abcdef;
int n = per;
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_VLAN);
std::vector<swss::FieldValueTuple> entries;
for (int idx = 0; idx < n; ++idx)
{
std::string str_attr = "";
swss::FieldValueTuple fvtNoStatus(sai_serialize_object_id(oid), str_attr);
entries.push_back(fvtNoStatus);
}
std::string joined;
for (const auto &e: entries)
{
joined += "||" + fvField(e);
}
return str_object_type + ":" + std::to_string(entries.size()) + joined;
}
void test_serialize_bulk_remove_oid(int n, int per)
{
SWSS_LOG_ENTER();
auto str = serialize_bulk_vlan(per);
std::cout << str.substr(0,100) << " ... len " << str.size() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_bulk_vlan(per);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
//std::cout << "ms: " << (double)us.count()/1000 << " n " << n << " x / per " << per << std::endl;
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
}
std::string serialize_bulk_route_entry(int per)
{
SWSS_LOG_ENTER();
static auto route_entry = get_route_entry();
int n = per;
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_ROUTE_ENTRY);
std::vector<swss::FieldValueTuple> entries;
for (int idx = 0; idx < n; ++idx)
{
std::string str_attr = "";
swss::FieldValueTuple fvtNoStatus(sai_serialize_route_entry(route_entry), str_attr);
entries.push_back(fvtNoStatus);
}
std::string joined;
for (const auto &e: entries)
{
joined += "||" + fvField(e);
}
return str_object_type + ":" + std::to_string(entries.size()) + joined;
}
void test_serialize_bulk_remove_route_entry(int n, int per)
{
SWSS_LOG_ENTER();
auto str = serialize_bulk_route_entry(per);
std::cout << str.substr(0,100) << " ... len " << str.size() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_bulk_route_entry(per);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
//std::cout << "ms: " << (double)us.count()/1000 << " n " << n << " x / per " << per << std::endl;
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
}
std::string serialize_bulk_fdb_entry(int per)
{
SWSS_LOG_ENTER();
static auto fdb_entry = get_fdb_entry();
int n = per;
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_FDB_ENTRY);
std::vector<swss::FieldValueTuple> entries;
for (int idx = 0; idx < n; ++idx)
{
std::string str_attr = "";
swss::FieldValueTuple fvtNoStatus(sai_serialize_fdb_entry(fdb_entry), str_attr);
entries.push_back(fvtNoStatus);
}
std::string joined;
for (const auto &e: entries)
{
joined += "||" + fvField(e);
}
return str_object_type + ":" + std::to_string(entries.size()) + joined;
}
void test_serialize_bulk_remove_fdb_entry(int n, int per)
{
SWSS_LOG_ENTER();
auto str = serialize_bulk_fdb_entry(per);
std::cout << str.substr(0,100) << " ... len " << str.size() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_bulk_fdb_entry(per);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
//std::cout << "ms: " << (double)us.count()/1000 << " n " << n << " x / per " << per << std::endl;
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
}
const std::vector<swss::FieldValueTuple> get_values(const std::vector<std::string>& items)
{
SWSS_LOG_ENTER();
std::vector<swss::FieldValueTuple> values;
// timestamp|action|objecttype:objectid|attrid=value,...
for (size_t i = 3; i <items.size(); ++i)
{
const std::string& item = items[i];
auto start = item.find_first_of("=");
auto field = item.substr(0, start);
auto value = item.substr(start + 1);
swss::FieldValueTuple entry(field, value);
values.push_back(entry);
}
return values;
}
SaiAttributeList* get_route_entry_list()
{
SWSS_LOG_ENTER();
std::vector<swss::FieldValueTuple> values;
values.push_back(swss::FieldValueTuple("SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION","SAI_PACKET_ACTION_FORWARD"));
values.push_back(swss::FieldValueTuple("SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID","oid:0x1000000000001"));
return new SaiAttributeList(SAI_OBJECT_TYPE_ROUTE_ENTRY, values, false);
}
std::string serialize_create_route_entry()
{
SWSS_LOG_ENTER();
static auto route_entry = get_route_entry();
static SaiAttributeList *list = get_route_entry_list();
std::vector<swss::FieldValueTuple> entry = SaiAttributeList::serialize_attr_list(
SAI_OBJECT_TYPE_ROUTE_ENTRY,
list->get_attr_count(),
list->get_attr_list(),
false);
std::string joined;
for (const auto &e: entry)
{
joined += "||" + fvField(e) + "|" + fvValue(e);
}
return sai_serialize_object_type(SAI_OBJECT_TYPE_ROUTE_ENTRY) + ":" +
sai_serialize_route_entry(route_entry) + ":" + joined;
}
void test_serialize_create_route_entry(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_create_route_entry() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_create_route_entry();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
SaiAttributeList* get_fdb_entry_list()
{
SWSS_LOG_ENTER();
std::vector<swss::FieldValueTuple> values;
values.push_back(swss::FieldValueTuple("SAI_FDB_ENTRY_ATTR_TYPE","SAI_FDB_ENTRY_TYPE_DYNAMIC"));
values.push_back(swss::FieldValueTuple("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID","oid:0x3a000000000fb"));
values.push_back(swss::FieldValueTuple("SAI_FDB_ENTRY_ATTR_PACKET_ACTION","SAI_PACKET_ACTION_FORWARD"));
return new SaiAttributeList(SAI_OBJECT_TYPE_FDB_ENTRY, values, false);
}
std::string serialize_create_fdb_entry()
{
SWSS_LOG_ENTER();
static auto fdb_entry = get_fdb_entry();
static SaiAttributeList *list = get_fdb_entry_list();
std::vector<swss::FieldValueTuple> entry = SaiAttributeList::serialize_attr_list(
SAI_OBJECT_TYPE_FDB_ENTRY,
list->get_attr_count(),
list->get_attr_list(),
false);
std::string joined;
for (const auto &e: entry)
{
joined += "||" + fvField(e) + "|" + fvValue(e);
}
return sai_serialize_object_type(SAI_OBJECT_TYPE_FDB_ENTRY) + ":" +
sai_serialize_fdb_entry(fdb_entry) + ":" + joined;
}
void test_serialize_create_fdb_entry(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_create_fdb_entry() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_create_fdb_entry();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
SaiAttributeList* get_oid_list()
{
SWSS_LOG_ENTER();
std::vector<swss::FieldValueTuple> values;
values.push_back(swss::FieldValueTuple("SAI_VLAN_ATTR_VLAN_ID","2"));
return new SaiAttributeList(SAI_OBJECT_TYPE_VLAN, values, false);
}
std::string serialize_create_oid()
{
SWSS_LOG_ENTER();
static sai_object_id_t oid = 0x123456789abcdef;
static SaiAttributeList *list = get_oid_list();
std::vector<swss::FieldValueTuple> entry = SaiAttributeList::serialize_attr_list(
SAI_OBJECT_TYPE_VLAN,
list->get_attr_count(),
list->get_attr_list(),
false);
std::string joined;
for (const auto &e: entry)
{
joined += "||" + fvField(e) + "|" + fvValue(e);
}
return sai_serialize_object_type(SAI_OBJECT_TYPE_VLAN) + ":" +
sai_serialize_object_id(oid) + "|" + joined;
}
void test_serialize_create_oid(int n)
{
SWSS_LOG_ENTER();
std::cout << serialize_create_oid() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_create_oid();
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000 << " / " << n << std::endl;
}
std::string serialize_bulk_create_route_entry(int per)
{
SWSS_LOG_ENTER();
static auto route_entry = get_route_entry();
static SaiAttributeList *list = get_route_entry_list();
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_ROUTE_ENTRY);
std::vector<swss::FieldValueTuple> entries;
for (int idx = 0; idx < per; ++idx)
{
std::vector<swss::FieldValueTuple> entry =
SaiAttributeList::serialize_attr_list(SAI_OBJECT_TYPE_ROUTE_ENTRY, list->get_attr_count(), list->get_attr_list(), false);
std::string str_attr = Globals::joinFieldValues(entry);
std::string str_status = sai_serialize_status(SAI_STATUS_NOT_EXECUTED);
std::string joined = str_attr + "|" + str_status;
swss::FieldValueTuple fvt(sai_serialize_route_entry(route_entry) , joined);
entries.push_back(fvt);
}
std::string joined;
for (const auto &e: entries)
{
joined += "||" + fvField(e) + "|" + fvValue(e);
}
return str_object_type + ":" + std::to_string(entries.size()) + joined;
}
void test_serialize_bulk_create_route_entry(int n, int per)
{
SWSS_LOG_ENTER();
auto str = serialize_bulk_create_route_entry(per);
std::cout << str.substr(0,300) << " ... len " << str.size() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_bulk_route_entry(per);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
//std::cout << "ms: " << (double)us.count()/1000 << " n " << n << " x / per " << per << std::endl;
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
}
std::string serialize_bulk_create_oid(int per)
{
SWSS_LOG_ENTER();
static sai_object_id_t oid = 0x123456789abcdef;
static SaiAttributeList *list = get_oid_list();
std::string str_object_type = sai_serialize_object_type(SAI_OBJECT_TYPE_VLAN);
std::vector<swss::FieldValueTuple> entries;
for (int idx = 0; idx < per; ++idx)
{
std::vector<swss::FieldValueTuple> entry =
SaiAttributeList::serialize_attr_list(SAI_OBJECT_TYPE_VLAN, list->get_attr_count(), list->get_attr_list(), false);
std::string str_attr = Globals::joinFieldValues(entry);
std::string str_status = sai_serialize_status(SAI_STATUS_NOT_EXECUTED);
std::string joined = str_attr + "|" + str_status;
swss::FieldValueTuple fvt(sai_serialize_object_id(oid) , joined);
entries.push_back(fvt);
}
std::string joined;
for (const auto &e: entries)
{
joined += "||" + fvField(e) + "|" + fvValue(e);
}
return str_object_type + ":" + std::to_string(entries.size()) + joined;
}
void test_serialize_bulk_create_oid(int n, int per)
{
SWSS_LOG_ENTER();
auto str = serialize_bulk_create_oid(per);
std::cout << str.substr(0,300) << " ... len " << str.size() << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
auto s = serialize_bulk_create_oid(per);
}
auto end = std::chrono::high_resolution_clock::now();
auto time = end - start;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
//std::cout << "ms: " << (double)us.count()/1000 << " n " << n << " x / per " << per << std::endl;
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
}
void test_ContextConfigContainer()
{
SWSS_LOG_ENTER();
auto ccc = ContextConfigContainer::loadFromFile("context_config.json");
}
static std::vector<std::string> tokenize(
_In_ std::string input,
_In_ const std::string &delim)
{
SWSS_LOG_ENTER();
/*
* input is modified so it can't be passed as reference
*/
std::vector<std::string> tokens;
size_t pos = 0;
while ((pos = input.find(delim)) != std::string::npos)
{
std::string token = input.substr(0, pos);
input.erase(0, pos + delim.length());
tokens.push_back(token);
}
tokens.push_back(input);
return tokens;
}
static sai_object_type_t deserialize_object_type(
_In_ const std::string& s)
{
SWSS_LOG_ENTER();
sai_object_type_t object_type;
sai_deserialize_object_type(s, object_type);
return object_type;
}
static std::vector<std::string> parseFirstRecordedAPI()
{
SWSS_LOG_ENTER();
std::ifstream infile(SairedisRecFilename);
std::string line;
// skip first line
std::getline(infile, line);
std::getline(infile, line);
std::vector<std::string> tokens;
std::stringstream sstream(line);
std::string token;
const auto delimiter = '|';
// skip first, it is a timestamp
std::getline(sstream, token, delimiter);
while(std::getline(sstream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
}
static void test_recorder_enum_value_capability_query_request(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_In_ sai_attr_id_t attr_id,
_In_ const std::vector<std::string>& expectedOutput)
{
SWSS_LOG_ENTER();
remove(SairedisRecFilename.c_str());
Recorder recorder;
recorder.enableRecording(true);
sai_s32_list_t enum_values_capability { .count = 0, .list = nullptr };
recorder.recordQueryAttributeEnumValuesCapability(
switch_id,
object_type,
attr_id,
&enum_values_capability
);
auto tokens = parseFirstRecordedAPI();
ASSERT_EQ(tokens, expectedOutput);
}
static void test_recorder_enum_value_capability_query_response(
_In_ sai_status_t status,
_In_ sai_object_type_t object_type,
_In_ sai_attr_id_t attr_id,
_In_ std::vector<int32_t> enumList,
_In_ const std::vector<std::string>& expectedOutput)
{
SWSS_LOG_ENTER();
remove(SairedisRecFilename.c_str());
Recorder recorder;
recorder.enableRecording(true);
sai_s32_list_t enum_values_capability;
enum_values_capability.count = static_cast<int32_t>(enumList.size());
enum_values_capability.list = enumList.data();
recorder.recordQueryAttributeEnumValuesCapabilityResponse(
status,
object_type,
attr_id,
&enum_values_capability
);
auto tokens = parseFirstRecordedAPI();
ASSERT_EQ(tokens, expectedOutput);
}
static void test_recorder_enum_value_capability_query()
{
SWSS_LOG_ENTER();
test_recorder_enum_value_capability_query_request(
1,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
SAI_DEBUG_COUNTER_ATTR_TYPE,
{
"q",
"attribute_enum_values_capability",
"SAI_OBJECT_TYPE_SWITCH:oid:0x1",
"SAI_DEBUG_COUNTER_ATTR_TYPE=0",
}
);
test_recorder_enum_value_capability_query_response(
SAI_STATUS_SUCCESS,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
SAI_DEBUG_COUNTER_ATTR_TYPE,
{
SAI_DEBUG_COUNTER_TYPE_PORT_IN_DROP_REASONS,
SAI_DEBUG_COUNTER_TYPE_PORT_OUT_DROP_REASONS,
SAI_DEBUG_COUNTER_TYPE_SWITCH_IN_DROP_REASONS,
SAI_DEBUG_COUNTER_TYPE_SWITCH_OUT_DROP_REASONS,
},
{
"Q",
"attribute_enum_values_capability",
"SAI_STATUS_SUCCESS",
"SAI_DEBUG_COUNTER_ATTR_TYPE=4:SAI_DEBUG_COUNTER_TYPE_PORT_IN_DROP_REASONS,SAI_DEBUG_COUNTER_TYPE_PORT_OUT_DROP_REASONS,"
"SAI_DEBUG_COUNTER_TYPE_SWITCH_IN_DROP_REASONS,SAI_DEBUG_COUNTER_TYPE_SWITCH_OUT_DROP_REASONS",
}
);
test_recorder_enum_value_capability_query_request(
1,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST,
{
"q",
"attribute_enum_values_capability",
"SAI_OBJECT_TYPE_SWITCH:oid:0x1",
"SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST=0",
}
);
test_recorder_enum_value_capability_query_response(
SAI_STATUS_SUCCESS,
SAI_OBJECT_TYPE_DEBUG_COUNTER,
SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST,
{
SAI_IN_DROP_REASON_L2_ANY,
SAI_IN_DROP_REASON_L3_ANY
},
{
"Q",
"attribute_enum_values_capability",
"SAI_STATUS_SUCCESS",
"SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST=2:SAI_IN_DROP_REASON_L2_ANY,SAI_IN_DROP_REASON_L3_ANY"
}
);
}
void test_tokenize_bulk_route_entry()
{
SWSS_LOG_ENTER();
auto header = "2020-09-24.21:06:54.045505|C|SAI_OBJECT_TYPE_ROUTE_ENTRY";
auto route = "||{\"dest\":\"20c1:bb0:0:80::/64\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x3000000000022\"}|SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID=oid:0x500000000066c";
std::string line = header;
int per = 100;
for (int i = 0; i < per; i++)
{
line += route;
}
auto tstart = std::chrono::high_resolution_clock::now();
int n = 1000;
for (int c = 0; c < n; c++)
{
auto fields = tokenize(line, "||");
auto first = fields.at(0); // timestamp|action|objecttype
std::string str_object_type = swss::tokenize(first, '|').at(2);
sai_object_type_t object_type = deserialize_object_type(str_object_type);
std::vector<std::string> object_ids;
std::vector<std::shared_ptr<SaiAttributeList>> attributes;
for (size_t idx = 1; idx < fields.size(); ++idx)
{
// object_id|attr=value|...
const std::string &joined = fields[idx];
auto split = swss::tokenize(joined, '|');
std::string str_object_id = split.front();
object_ids.push_back(str_object_id);
std::vector<swss::FieldValueTuple> entries; // attributes per object id
SWSS_LOG_DEBUG("processing: %s", joined.c_str());
for (size_t i = 1; i < split.size(); ++i)
{
const auto &item = split[i];
auto start = item.find_first_of("=");
auto field = item.substr(0, start);
auto value = item.substr(start + 1);
swss::FieldValueTuple entry(field, value);
entries.push_back(entry);
}
// since now we converted this to proper list, we can extract attributes
std::shared_ptr<SaiAttributeList> list =
std::make_shared<SaiAttributeList>(object_type, entries, false);
attributes.push_back(list);
}
}
auto tend = std::chrono::high_resolution_clock::now();
auto time = tend - tstart;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(time);
std::cout << "ms: " << (double)us.count()/1000.0 / n << " n " << n << " / per " << per << std::endl;
std::cout << "s: " << (double)us.count()/1000000.0 << " for total routes: " <<( n * per) << std::endl;
}
static void test_recorder_stats_capability_query_request(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_In_ const std::vector<std::string>& expectedOutput)
{
SWSS_LOG_ENTER();
remove(SairedisRecFilename.c_str());
Recorder recorder;
recorder.enableRecording(true);
sai_stat_capability_list_t stats_capability;
sai_stat_capability_t cap_list;
cap_list.stat_enum = SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES;
cap_list.stat_modes = SAI_STATS_MODE_READ;
stats_capability.count = 1;
stats_capability.list = &cap_list;
recorder.recordQueryStatsCapability(1, SAI_OBJECT_TYPE_QUEUE, &stats_capability);
auto tokens = parseFirstRecordedAPI();
ASSERT_EQ(tokens, expectedOutput);
}
static void test_recorder_stats_capability_query_response(
_In_ sai_object_id_t switch_id,
_In_ sai_object_type_t object_type,
_In_ const std::vector<std::string>& expectedOutput)
{
SWSS_LOG_ENTER();
remove(SairedisRecFilename.c_str());
Recorder recorder;
recorder.enableRecording(true);
sai_stat_capability_list_t stats_capability;
sai_stat_capability_t cap_list;
cap_list.stat_enum = SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES;
cap_list.stat_modes = SAI_STATS_MODE_READ;
stats_capability.count = 1;
stats_capability.list = &cap_list;
recorder.recordQueryStatsCapabilityResponse(SAI_STATUS_SUCCESS , SAI_OBJECT_TYPE_QUEUE, &stats_capability);
auto tokens = parseFirstRecordedAPI();
recorder.recordQueryStatsCapabilityResponse(SAI_STATUS_SUCCESS , SAI_OBJECT_TYPE_MAX, &stats_capability);
recorder.recordQueryStatsCapabilityResponse(SAI_STATUS_SUCCESS , SAI_OBJECT_TYPE_BRIDGE_PORT , &stats_capability);
ASSERT_EQ(tokens, expectedOutput);
}
static void test_recorder_stats_capability_query()
{
SWSS_LOG_ENTER();
Recorder recorder;
remove(SairedisRecFilename.c_str());
recorder.enableRecording(true);
const std::vector<std::string> expectedOutputQuery =
{
"q",
"stats_capability",
"SAI_OBJECT_TYPE_SWITCH:oid:0x1",
"OBJECT_TYPE=SAI_OBJECT_TYPE_QUEUE",
"LIST_SIZE=1",
};
const std::vector<std::string> expectedOutputResponse =
{
"Q",
"stats_capability",
"SAI_STATUS_SUCCESS",
"{\"count\":1,\"list\":[{\"stat_enum\":\"SAI_QUEUE_STAT_WRED_ECN_MARKED_BYTES\",\"stat_modes\":[\"SAI_STATS_MODE_READ\"]}]}",
};
test_recorder_stats_capability_query_request(1,
SAI_OBJECT_TYPE_QUEUE,
expectedOutputQuery
);
test_recorder_stats_capability_query_response(1,
SAI_OBJECT_TYPE_QUEUE,
expectedOutputResponse
);
}
int main()
{
SWSS_LOG_ENTER();
std::cout << " * test tokenize bulk route entry" << std::endl;
test_tokenize_bulk_route_entry();
std::cout << " * test ContextConfigContainer" << std::endl;
test_ContextConfigContainer();
std::cout << " * test deserialize route_entry" << std::endl;
test_deserialize_route_entry_meta(10000);
test_deserialize_route_entry(10000);
std::cout << " * test remove" << std::endl;
test_serialize_remove_route_entry(10000);
test_serialize_remove_fdb_entry(10000);
test_serialize_remove_oid(10000);
std::cout << " * test bulk remove" << std::endl;
test_serialize_bulk_remove_route_entry(10,10000);
test_serialize_bulk_remove_fdb_entry(10,10000);
test_serialize_bulk_remove_oid(100,10000);
std::cout << " * test create" << std::endl;
test_serialize_create_route_entry(10000);
test_serialize_create_fdb_entry(10000);
test_serialize_create_oid(10000);
std::cout << " * test bulk create" << std::endl;
test_serialize_bulk_create_route_entry(10,10000);
test_serialize_bulk_create_oid(10,10000);
std::cout << " * test recorder" << std::endl;
test_recorder_enum_value_capability_query();
test_recorder_stats_capability_query();
return 0;
}