Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"RDMA_SHARED_POOL_SIZE_CHANGE__FAILURE": {
"desc": "For RDMA shared pool size tuning- adjust both shared pool and headroom pool",
"current_config": {
"BUFFER_POOL": {
"ingress_lossless_pool": {
"xoff": "4194112",
"type": "ingress",
"mode": "dynamic",
"size": "10875072"
},
"egress_lossless_pool": {
"type": "egress",
"mode": "static",
Copy link
Copy Markdown
Contributor

@qiluo-msft qiluo-msft Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

       [](http://example.com/codeflow?start=0&length=6)

You mixed tabs and spaces. Could you stick with 4-space indentation? #Closed

"size": "15982720"
},
"egress_lossy_pool": {
"type": "egress",
"mode": "dynamic",
"size": "9243812"
}
}
},
"patch": [
{
"op": "replace",
"path": "/BUFFER_POOL/ingress_lossless_pool/xoff",
"value": "invalid_xoff"
}
],
"expected_error_substrings": [
"Given patch will produce invalid config"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"RDMA_SHARED_POOL_SIZE_CHANGE__SUCCESS": {
"desc": "For RDMA shared pool size tuning- adjust both shared pool and headroom pool",
"current_config": {
"BUFFER_POOL": {
"ingress_lossless_pool": {
"xoff": "4194112",
"type": "ingress",
"mode": "dynamic",
"size": "10875072"
},
"egress_lossless_pool": {
"type": "egress",
"mode": "static",
"size": "15982720"
},
"egress_lossy_pool": {
"type": "egress",
"mode": "dynamic",
"size": "9243812"
}
}
},
"patch": [
{
"op": "replace",
"path": "/BUFFER_POOL/ingress_lossless_pool/xoff",
"value": "2155712"
},
{
"op": "replace",
"path": "/BUFFER_POOL/ingress_lossless_pool/size",
"value": "12913472"
},
{
"op": "replace",
"path": "/BUFFER_POOL/egress_lossy_pool/size",
"value": "5200000"
}
],
"expected_config": {
"BUFFER_POOL": {
"ingress_lossless_pool": {
"xoff": "2155712",
"type": "ingress",
"mode": "dynamic",
"size": "12913472"
},
"egress_lossless_pool": {
"type": "egress",
"mode": "static",
"size": "15982720"
},
"egress_lossy_pool": {
"type": "egress",
"mode": "dynamic",
"size": "5200000"
}
}
}
}
}
95 changes: 95 additions & 0 deletions tests/generic_config_updater/gcu_feature_patch_application_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import jsonpatch
import unittest
from unittest.mock import MagicMock, Mock

import generic_config_updater.patch_sorter as ps
from .gutest_helpers import Files
from generic_config_updater.gu_common import ConfigWrapper, PatchWrapper


class TestFeaturePatchApplication(unittest.TestCase):
def setUp(self):
self.config_wrapper = ConfigWrapper()

def test_feature_patch_application_success(self):
# Format of the JSON file containing the test-cases:
#
# {
# "<unique_name_for_the_test>":{
# "desc":"<brief explanation of the test case>",
# "current_config":<the running config to be modified>,
# "patch":<the JsonPatch to apply>,
# "expected_config":<the config after jsonpatch modification>
# },
# .
# .
# .
# }
data = Files.FEATURE_PATCH_APPLICATION_TEST_SUCCESS

for test_case_name in data:
with self.subTest(name=test_case_name):
self.run_single_success_case(data[test_case_name])

def test_feature_patch_application_failure(self):
# Fromat of the JSON file containing the test-cases:
#
# {
# "<unique_name_for_the_test>":{
# "desc":"<brief explanation of the test case>",
# "current_config":<the running config to be modified>,
# "patch":<the JsonPatch to apply>,
# "expected_error_substrings":<error substrings expected in failure output>
# },
# .
# .
# .
# }
data = Files.FEATURE_PATCH_APPLICATION_TEST_FAILURE

for test_case_name in data:
with self.subTest(name=test_case_name):
self.run_single_failure_case(data[test_case_name])

def create_strict_patch_sorter(self, config):
config_wrapper = self.config_wrapper
config_wrapper.get_config_db_as_json = MagicMock(return_value=config)
patch_wrapper = PatchWrapper(config_wrapper)
return ps.StrictPatchSorter(config_wrapper, patch_wrapper)

def run_single_success_case(self, data):
current_config = data["current_config"]
expected_config = data["expected_config"]
patch = jsonpatch.JsonPatch(data["patch"])
sorter = self.create_strict_patch_sorter(current_config)
actual_changes = sorter.sort(patch)
target_config = patch.apply(current_config)
simulated_config = current_config

for change in actual_changes:
simulated_config = change.apply(simulated_config)
is_valid, error = self.config_wrapper.validate_config_db_config(simulated_config)
self.assertTrue(is_valid, f"Change will produce invalid config. Error: {error}")

self.assertEqual(target_config, simulated_config)
self.assertEqual(simulated_config, expected_config)

def run_single_failure_case(self, data):
current_config = data["current_config"]
patch = jsonpatch.JsonPatch(data["patch"])
expected_error_substrings = data["expected_error_substrings"]

try:
sorter = self.create_strict_patch_sorter(current_config)
sorter.sort(patch)
self.fail("An exception was supposed to be thrown")
except Exception as ex:
notfound_substrings = []
error = str(ex)

for substring in expected_error_substrings:
if substring not in error:
notfound_substrings.append(substring)

if notfound_substrings:
self.fail(f"Did not find the expected substrings {notfound_substrings} in the error: '{error}'")