Skip to content

Commit b817342

Browse files
authored
[GCU] Add Sample Unit Test for RDMA Headroom Pool Size Tuning (#2692)
* add rdma gcu unit test * fix comment * clean unused code * clean format * extend to mock patchapplier, in place of changeapplier * replace tabs with spaces
1 parent 6f84aae commit b817342

File tree

3 files changed

+214
-0
lines changed

3 files changed

+214
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"RDMA_SHARED_POOL_SIZE_CHANGE__FAILURE": {
3+
"desc": "For RDMA shared pool size tuning- adjust both shared pool and headroom pool",
4+
"current_config": {
5+
"BUFFER_POOL": {
6+
"ingress_lossless_pool": {
7+
"xoff": "4194112",
8+
"type": "ingress",
9+
"mode": "dynamic",
10+
"size": "10875072"
11+
},
12+
"egress_lossless_pool": {
13+
"type": "egress",
14+
"mode": "static",
15+
"size": "15982720"
16+
},
17+
"egress_lossy_pool": {
18+
"type": "egress",
19+
"mode": "dynamic",
20+
"size": "9243812"
21+
}
22+
}
23+
},
24+
"patch": [
25+
{
26+
"op": "replace",
27+
"path": "/BUFFER_POOL/ingress_lossless_pool/xoff",
28+
"value": "invalid_xoff"
29+
}
30+
],
31+
"expected_error_substrings": [
32+
"Given patch will produce invalid config"
33+
]
34+
}
35+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"RDMA_SHARED_POOL_SIZE_CHANGE__SUCCESS": {
3+
"desc": "For RDMA shared pool size tuning- adjust both shared pool and headroom pool",
4+
"current_config": {
5+
"BUFFER_POOL": {
6+
"ingress_lossless_pool": {
7+
"xoff": "4194112",
8+
"type": "ingress",
9+
"mode": "dynamic",
10+
"size": "10875072"
11+
},
12+
"egress_lossless_pool": {
13+
"type": "egress",
14+
"mode": "static",
15+
"size": "15982720"
16+
},
17+
"egress_lossy_pool": {
18+
"type": "egress",
19+
"mode": "dynamic",
20+
"size": "9243812"
21+
}
22+
}
23+
},
24+
"patch": [
25+
{
26+
"op": "replace",
27+
"path": "/BUFFER_POOL/ingress_lossless_pool/xoff",
28+
"value": "2155712"
29+
},
30+
{
31+
"op": "replace",
32+
"path": "/BUFFER_POOL/ingress_lossless_pool/size",
33+
"value": "12913472"
34+
},
35+
{
36+
"op": "replace",
37+
"path": "/BUFFER_POOL/egress_lossy_pool/size",
38+
"value": "5200000"
39+
}
40+
],
41+
"expected_config": {
42+
"BUFFER_POOL": {
43+
"ingress_lossless_pool": {
44+
"xoff": "2155712",
45+
"type": "ingress",
46+
"mode": "dynamic",
47+
"size": "12913472"
48+
},
49+
"egress_lossless_pool": {
50+
"type": "egress",
51+
"mode": "static",
52+
"size": "15982720"
53+
},
54+
"egress_lossy_pool": {
55+
"type": "egress",
56+
"mode": "dynamic",
57+
"size": "5200000"
58+
}
59+
}
60+
}
61+
}
62+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import jsonpatch
2+
import unittest
3+
import copy
4+
from unittest.mock import MagicMock, Mock
5+
from mock import patch
6+
7+
import generic_config_updater.change_applier
8+
import generic_config_updater.patch_sorter as ps
9+
import generic_config_updater.generic_updater as gu
10+
from .gutest_helpers import Files
11+
from generic_config_updater.gu_common import ConfigWrapper, PatchWrapper
12+
13+
running_config = {}
14+
15+
def set_entry(config_db, tbl, key, data):
16+
global running_config
17+
if data != None:
18+
if tbl not in running_config:
19+
running_config[tbl] = {}
20+
running_config[tbl][key] = data
21+
else:
22+
assert tbl in running_config
23+
assert key in running_config[tbl]
24+
running_config[tbl].pop(key)
25+
if not running_config[tbl]:
26+
running_config.pop(tbl)
27+
28+
def get_running_config():
29+
return running_config
30+
31+
class TestFeaturePatchApplication(unittest.TestCase):
32+
def setUp(self):
33+
self.config_wrapper = ConfigWrapper()
34+
35+
def test_feature_patch_application_success(self):
36+
# Format of the JSON file containing the test-cases:
37+
#
38+
# {
39+
# "<unique_name_for_the_test>":{
40+
# "desc":"<brief explanation of the test case>",
41+
# "current_config":<the running config to be modified>,
42+
# "patch":<the JsonPatch to apply>,
43+
# "expected_config":<the config after jsonpatch modification>
44+
# },
45+
# .
46+
# .
47+
# .
48+
# }
49+
data = Files.FEATURE_PATCH_APPLICATION_TEST_SUCCESS
50+
51+
for test_case_name in data:
52+
with self.subTest(name=test_case_name):
53+
self.run_single_success_case_applier(data[test_case_name])
54+
55+
def test_feature_patch_application_failure(self):
56+
# Fromat of the JSON file containing the test-cases:
57+
#
58+
# {
59+
# "<unique_name_for_the_test>":{
60+
# "desc":"<brief explanation of the test case>",
61+
# "current_config":<the running config to be modified>,
62+
# "patch":<the JsonPatch to apply>,
63+
# "expected_error_substrings":<error substrings expected in failure output>
64+
# },
65+
# .
66+
# .
67+
# .
68+
# }
69+
data = Files.FEATURE_PATCH_APPLICATION_TEST_FAILURE
70+
71+
for test_case_name in data:
72+
with self.subTest(name=test_case_name):
73+
self.run_single_failure_case_applier(data[test_case_name])
74+
75+
def create_patch_applier(self, config):
76+
global running_config
77+
running_config = copy.deepcopy(config)
78+
config_wrapper = self.config_wrapper
79+
config_wrapper.get_config_db_as_json = MagicMock(side_effect=get_running_config)
80+
change_applier = generic_config_updater.change_applier.ChangeApplier()
81+
change_applier._get_running_config = MagicMock(side_effect=get_running_config)
82+
patch_wrapper = PatchWrapper(config_wrapper)
83+
return gu.PatchApplier(config_wrapper=config_wrapper, patch_wrapper=patch_wrapper, changeapplier=change_applier)
84+
85+
@patch("generic_config_updater.change_applier.get_config_db")
86+
@patch("generic_config_updater.change_applier.set_config")
87+
def run_single_success_case_applier(self, data, mock_set, mock_db):
88+
current_config = data["current_config"]
89+
mock_set.side_effect = set_entry
90+
expected_config = data["expected_config"]
91+
patch = jsonpatch.JsonPatch(data["patch"])
92+
patch_applier = self.create_patch_applier(current_config)
93+
patch_applier.apply(patch)
94+
result_config = patch_applier.config_wrapper.get_config_db_as_json()
95+
96+
self.assertEqual(expected_config, result_config)
97+
98+
@patch("generic_config_updater.change_applier.get_config_db")
99+
def run_single_failure_case_applier(self, data, mock_db):
100+
current_config = data["current_config"]
101+
patch = jsonpatch.JsonPatch(data["patch"])
102+
expected_error_substrings = data["expected_error_substrings"]
103+
104+
try:
105+
patch_applier = self.create_patch_applier(current_config)
106+
patch_applier.apply(patch)
107+
self.fail("An exception was supposed to be thrown")
108+
except Exception as ex:
109+
notfound_substrings = []
110+
error = str(ex)
111+
112+
for substring in expected_error_substrings:
113+
if substring not in error:
114+
notfound_substrings.append(substring)
115+
116+
if notfound_substrings:
117+
self.fail(f"Did not find the expected substrings {notfound_substrings} in the error: '{error}'")

0 commit comments

Comments
 (0)