Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hash]: Add UT infra #2660

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from dvslib import dvs_lag
from dvslib import dvs_mirror
from dvslib import dvs_policer
from dvslib import dvs_hash

from buffer_model import enable_dynamic_buffer

Expand Down Expand Up @@ -151,6 +152,8 @@ def _populate_default_asic_db_values(self) -> None:
self.default_acl_tables = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE")
self.default_acl_entries = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY")

self.default_hash_keys = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_HASH")

self.default_copp_policers = self.get_keys("ASIC_STATE:SAI_OBJECT_TYPE_POLICER")


Expand Down Expand Up @@ -1338,6 +1341,7 @@ def get_asic_db(self) -> AsicDbValidator:
db = DVSDatabase(self.ASIC_DB_ID, self.redis_sock)
db.default_acl_tables = self.asicdb.default_acl_tables
db.default_acl_entries = self.asicdb.default_acl_entries
db.default_hash_keys = self.asicdb.default_hash_keys
db.default_copp_policers = self.asicdb.default_copp_policers
db.port_name_map = self.asicdb.portnamemap
db.default_vlan_id = self.asicdb.default_vlan_id
Expand Down Expand Up @@ -1916,6 +1920,11 @@ def dvs_policer_manager(request, dvs):
request.cls.dvs_policer = dvs_policer.DVSPolicer(dvs.get_asic_db(),
dvs.get_config_db())

@pytest.fixture(scope="class")
def dvs_hash_manager(request, dvs):
request.cls.dvs_hash = dvs_hash.DVSHash(dvs.get_asic_db(),
dvs.get_config_db())

##################### DPB fixtures ###########################################
def create_dpb_config_file(dvs):
cmd = "sonic-cfggen -j /etc/sonic/init_cfg.json -j /tmp/ports.json --print-data > /tmp/dpb_config_db.json"
Expand Down
80 changes: 80 additions & 0 deletions tests/dvslib/dvs_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Utilities for interacting with HASH objects when writing VS tests."""
from typing import Dict, List


class DVSHash:
"""Manage hash objects on the virtual switch."""

CDB_SWITCH_HASH = "SWITCH_HASH"
KEY_SWITCH_HASH_GLOBAL = "GLOBAL"

ADB_HASH = "ASIC_STATE:SAI_OBJECT_TYPE_HASH"

def __init__(self, asic_db, config_db):
"""Create a new DVS hash manager."""
self.asic_db = asic_db
self.config_db = config_db

def update_switch_hash(
self,
qualifiers: Dict[str, str]
) -> None:
"""Update switch hash global in Config DB."""
self.config_db.update_entry(self.CDB_SWITCH_HASH, self.KEY_SWITCH_HASH_GLOBAL, qualifiers)

def get_hash_ids(
self,
expected: int = None
) -> List[str]:
"""Get all of the hash ids in ASIC DB.
Args:
expected: The number of hash ids that are expected to be present in ASIC DB.
Returns:
The list of hash ids in ASIC DB.
"""
if expected is None:
return self.asic_db.get_keys(self.ADB_HASH)

num_keys = len(self.asic_db.default_hash_keys) + expected
keys = self.asic_db.wait_for_n_keys(self.ADB_HASH, num_keys)

for k in self.asic_db.default_hash_keys:
assert k in keys

return [k for k in keys if k not in self.asic_db.default_hash_keys]

def verify_hash_count(
self,
expected: int
) -> None:
"""Verify that there are N hash objects in ASIC DB.
Args:
expected: The number of hash ids that are expected to be present in ASIC DB.
"""
self.get_hash_ids(expected)

def verify_hash_generic(
self,
sai_hash_id: str,
sai_qualifiers: Dict[str, str]
) -> None:
"""Verify that hash object has correct ASIC DB representation.
Args:
sai_hash_id: The specific hash id to check in ASIC DB.
sai_qualifiers: The expected set of SAI qualifiers to be found in ASIC DB.
"""
entry = self.asic_db.wait_for_entry(self.ADB_HASH, sai_hash_id)

for k, v in entry.items():
if k == "NULL":
continue
elif k in sai_qualifiers:
if k == "SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST":
hfList = v[v.index(":")+1:].split(",")
assert set(sai_qualifiers[k]) == set(hfList)
else:
assert False, "Unknown SAI qualifier: key={}, value={}".format(k, v)
17 changes: 2 additions & 15 deletions tests/dvslib/dvs_pbh.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class DVSPbh:
CDB_PBH_HASH_FIELD = "PBH_HASH_FIELD"

ADB_PBH_HASH = "ASIC_STATE:SAI_OBJECT_TYPE_HASH"
ADB_PBH_HASH_FIELD = "ASIC_STATE:SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD"

def __init__(self, asic_db, config_db):
"""Create a new DVS PBH Manager."""
Expand Down Expand Up @@ -110,13 +111,6 @@ def remove_pbh_hash(
"""Remove PBH hash from Config DB."""
self.config_db.delete_entry(self.CDB_PBH_HASH, hash_name)

def verify_pbh_hash_count(
self,
expected: int
) -> None:
"""Verify that there are N hash objects in ASIC DB."""
self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_HASH", expected)

def create_pbh_hash_field(
self,
hash_field_name: str,
Expand Down Expand Up @@ -147,11 +141,4 @@ def verify_pbh_hash_field_count(
expected: int
) -> None:
"""Verify that there are N hash field objects in ASIC DB."""
self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD", expected)

def get_pbh_hash_ids(
self,
expected: int
) -> List[str]:
"""Get all of the PBH hash IDs in ASIC DB."""
return self.asic_db.wait_for_n_keys(self.ADB_PBH_HASH, expected)
self.asic_db.wait_for_n_keys(self.ADB_PBH_HASH_FIELD, expected)
38 changes: 21 additions & 17 deletions tests/test_pbh.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def test_PbhTablePortChannelBinding(self, testlog):
self.dvs_lag.get_and_verify_port_channel(0)


@pytest.mark.usefixtures("dvs_hash_manager")
class TestPbhBasicFlows:
def test_PbhHashFieldCreationDeletion(self, testlog):
try:
Expand Down Expand Up @@ -162,12 +163,12 @@ def test_PbhHashCreationDeletion(self, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)
finally:
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand Down Expand Up @@ -205,7 +206,7 @@ def test_PbhRuleCreationDeletion(self, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)

# PBH table
pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME))
Expand Down Expand Up @@ -247,14 +248,15 @@ def test_PbhRuleCreationDeletion(self, testlog):
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
self.dvs_pbh.remove_pbh_hash_field(PBH_HASH_FIELD_NAME)
self.dvs_pbh.verify_pbh_hash_field_count(0)


@pytest.mark.usefixtures("dvs_hash_manager")
class TestPbhBasicEditFlows:
def test_PbhRuleUpdate(self, testlog):
try:
Expand All @@ -273,7 +275,7 @@ def test_PbhRuleUpdate(self, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)

# PBH table
pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME))
Expand Down Expand Up @@ -319,7 +321,7 @@ def test_PbhRuleUpdate(self, testlog):
flow_counter="ENABLED"
)

hash_id = self.dvs_pbh.get_pbh_hash_ids(1)[0]
hash_id = self.dvs_hash.get_hash_ids(1)[0]
counter_id = self.dvs_acl.get_acl_counter_ids(1)[0]

sai_attr_dict = {
Expand Down Expand Up @@ -352,7 +354,7 @@ def test_PbhRuleUpdate(self, testlog):
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand All @@ -377,7 +379,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)

# PBH table
pbhlogger.info("Create PBH table: {}".format(PBH_TABLE_NAME))
Expand Down Expand Up @@ -463,7 +465,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog):
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand All @@ -475,6 +477,7 @@ def test_PbhRuleUpdateFlowCounter(self, dvs, testlog):
test_flex_counters.post_trap_flow_counter_test(meta_data)


@pytest.mark.usefixtures("dvs_hash_manager")
@pytest.mark.usefixtures("dvs_lag_manager")
class TestPbhExtendedFlows:
class PbhRefCountHelper(object):
Expand Down Expand Up @@ -596,13 +599,13 @@ def create_hash(self, meta_dict, pbh_ref_count):
hash_field_list=meta_dict["hash_field_list"]
)
pbh_ref_count.incPbhHashCount()
self.dvs_pbh.verify_pbh_hash_count(pbh_ref_count.getPbhHashCount())
self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount())

def remove_hash(self, meta_dict, pbh_ref_count):
pbhlogger.info("Remove PBH hash: {}".format(meta_dict["name"]))
self.dvs_pbh.remove_pbh_hash(meta_dict["name"])
pbh_ref_count.decPbhHashCount()
self.dvs_pbh.verify_pbh_hash_count(pbh_ref_count.getPbhHashCount())
self.dvs_hash.verify_hash_count(pbh_ref_count.getPbhHashCount())

def create_table(self, meta_dict, pbh_ref_count):
pbhlogger.info("Create PBH table: {}".format(meta_dict["name"]))
Expand Down Expand Up @@ -909,6 +912,7 @@ def test_PbhNvgreVxlanConfiguration(self, testlog, pbh_nvgre, pbh_vxlan):
pass


@pytest.mark.usefixtures("dvs_hash_manager")
class TestPbhDependencyFlows:
def test_PbhHashCreationDeletionWithDependencies(self, testlog):
try:
Expand All @@ -918,7 +922,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand All @@ -928,7 +932,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog):
sequence_id=PBH_HASH_FIELD_SEQUENCE_ID
)
self.dvs_pbh.verify_pbh_hash_field_count(1)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)
finally:
# PBH hash field
pbhlogger.info("Remove PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand All @@ -938,7 +942,7 @@ def test_PbhHashCreationDeletionWithDependencies(self, testlog):
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)
self.dvs_pbh.verify_pbh_hash_field_count(0)

def test_PbhRuleCreationDeletionWithDependencies(self, testlog):
Expand All @@ -949,7 +953,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog):
hash_name=PBH_HASH_NAME,
hash_field_list=PBH_HASH_HASH_FIELD_LIST
)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)

# PBH hash field
pbhlogger.info("Create PBH hash field: {}".format(PBH_HASH_FIELD_NAME))
Expand All @@ -959,7 +963,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog):
sequence_id=PBH_HASH_FIELD_SEQUENCE_ID
)
self.dvs_pbh.verify_pbh_hash_field_count(1)
self.dvs_pbh.verify_pbh_hash_count(1)
self.dvs_hash.verify_hash_count(1)

# PBH rule
attr_dict = {
Expand Down Expand Up @@ -1009,7 +1013,7 @@ def test_PbhRuleCreationDeletionWithDependencies(self, testlog):
# PBH hash
pbhlogger.info("Remove PBH hash: {}".format(PBH_HASH_NAME))
self.dvs_pbh.remove_pbh_hash(PBH_HASH_NAME)
self.dvs_pbh.verify_pbh_hash_count(0)
self.dvs_hash.verify_hash_count(0)
self.dvs_pbh.verify_pbh_hash_field_count(0)


Expand Down