@@ -177,92 +177,62 @@ def test_rdma_config_update_validator_spc_asic_other_field(self):
177177 patch_element = {"path" : "/PFC_WD/Ethernet8/other_field" , "op" : "add" , "value" : "sample_value" }
178178 assert generic_config_updater .field_operation_validators .rdma_config_update_validator (patch_element ) == False
179179
180- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "20250530.12" }))
181- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "th5" ))
182- @patch ("os.path.exists" , mock .Mock (return_value = True ))
183- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
184- def test_wred_profile_config_update_validator_lossless (self ):
185- patch_element = {
186- "path" : "/WRED_PROFILE/AZURE_LOSSLESS/green_min_threshold" ,
187- "op" : "replace" ,
188- "value" : "1234"
189- }
190- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == True
191-
192- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "20250530.12" }))
193- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "th5" ))
194- @patch ("os.path.exists" , mock .Mock (return_value = True ))
195- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
196- def test_wred_profile_config_update_validator_lossy (self ):
197- patch_element = {
198- "path" : "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold" ,
199- "op" : "replace" ,
200- "value" : "1234"
201- }
202- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == True
203-
204- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "20250530.12" }))
205- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "th5" ))
206- @patch ("os.path.exists" , mock .Mock (return_value = True ))
207- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
208- def test_wred_profile_config_update_validator_invalid_field (self ):
209- patch_element = {
210- "path" : "/WRED_PROFILE/AZURE_LOSSY/invalid" ,
211- "op" : "replace" ,
212- "value" : "1234"
213- }
214- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == False
215-
216- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "unknown" ))
217- def test_wred_profile_config_update_validator_unknown_asic (self ):
218- patch_element = {
219- "path" : "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold" ,
220- "op" : "replace" ,
221- "value" : "1234"
222- }
223- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == False
224-
225- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "SONiC.20220530" }))
226- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "th5" ))
227- @patch ("os.path.exists" , mock .Mock (return_value = True ))
228- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
229- def test_wred_profile_config_update_validator_old_version (self ):
230- patch_element = {
231- "path" : "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold" ,
232- "op" : "replace" ,
233- "value" : "1234"
234- }
235- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == False
236-
237- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "20250530.12" }))
238- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "th5" ))
239- @patch ("os.path.exists" , mock .Mock (return_value = True ))
240- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
241- def test_wred_profile_config_update_validator_invalid_op (self ):
242- patch_element = {
243- "path" : "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold" ,
244- "op" : "add" ,
245- "value" : "1234"
246- }
247- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == False
248-
249- @patch ("sonic_py_common.device_info.get_sonic_version_info" , mock .Mock (return_value = {"build_version" : "20250530.12" }))
250- @patch ("generic_config_updater.field_operation_validators.get_asic_name" , mock .Mock (return_value = "spc1" ))
251- @patch ("os.path.exists" , mock .Mock (return_value = True ))
252- @patch ("builtins.open" , mock_open (read_data = '{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}' ))
253- def test_wred_profile_config_update_validator_invalid_asic (self ):
254- patch_element = {
255- "path" : "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold" ,
256- "op" : "replace" ,
257- "value" : "1234"
258- }
259- assert generic_config_updater .field_operation_validators .wred_profile_config_update_validator (patch_element ) == False
260-
261180 def test_validate_field_operation_illegal__pfcwd (self ):
262181 old_config = {"PFC_WD" : {"GLOBAL" : {"POLL_INTERVAL" : "60" }}}
263182 target_config = {"PFC_WD" : {"GLOBAL" : {}}}
264183 config_wrapper = gu_common .ConfigWrapper ()
265184 pytest .raises (gu_common .IllegalPatchOperationError , config_wrapper .validate_field_operation , old_config , target_config )
185+
186+ @patch ("sonic_py_common.device_info.get_sonic_version_info" ,
187+ mock .Mock (return_value = {"build_version" : "20241211.49" }))
188+ @patch ("generic_config_updater.field_operation_validators.get_asic_name" ,
189+ mock .Mock (return_value = "spc1" ))
190+ @patch ("os.path.exists" , mock .Mock (return_value = True ))
191+ @patch (
192+ "builtins.open" ,
193+ mock_open (
194+ read_data = (
195+ '{"tables": {"BUFFER_POOL": {'
196+ '"field_operation_validators": ['
197+ '"generic_config_updater.field_operation_validators.rdma_config_update_validator"'
198+ '], "validator_data": {"rdma_config_update_validator": {"Blocked ops": '
199+ '{"fields": ["ingress_lossless_pool/xoff", '
200+ '"ingress_lossless_pool/size", "egress_lossy_pool/size"], '
201+ '"operations": [], "platforms": {"spc1": "20181100"}}}}}}}'
202+ )
203+ )
204+ )
205+ def test_validate_field_operation_illegal__buffer_pool (self ):
206+ old_config = {
207+ "BUFFER_POOL" : {
208+ "ingress_lossless_pool" : {"xoff" : "1000" }
209+ }
210+ }
211+ target_config = {
212+ "BUFFER_POOL" : {
213+ "ingress_lossless_pool" : {"xoff" : "2000" }
214+ }
215+ }
216+ config_wrapper = gu_common .ConfigWrapper ()
217+ original_validator = fov .rdma_config_update_validator
218+
219+ def _rdma_validator_wrapper (* args , ** kwargs ):
220+ if args :
221+ patch_element = args [- 1 ]
222+ else :
223+ patch_element = kwargs .get ("patch_element" )
224+ return original_validator (patch_element )
225+
226+ with patch (
227+ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ,
228+ side_effect = _rdma_validator_wrapper ,
229+ ):
230+ pytest .raises (
231+ gu_common .IllegalPatchOperationError ,
232+ config_wrapper .validate_field_operation ,
233+ old_config ,
234+ target_config
235+ )
266236
267237 def test_validate_field_operation_legal__rm_loopback1 (self ):
268238 old_config = {
@@ -386,6 +356,150 @@ def test_validate_field_operation_legal__only_dataacl_rule_update(self):
386356 config_wrapper .validate_field_operation (old_config , target_config )
387357
388358
359+ @pytest .mark .parametrize (
360+ "field,old_value,new_value,op" , [
361+ ("ecn" , "ecn_all" , "ecn_green" , "replace" ),
362+ ("green_drop_probability" , "5" , "6" , "replace" ),
363+ ("green_max_threshold" , "136200192" , "136200193" , "replace" ),
364+ ("green_min_threshold" , "136200192" , "136200193" , "replace" ),
365+ ("red_drop_probability" , "5" , "6" , "replace" ),
366+ ("red_max_threshold" , "282624" , "282625" , "replace" ),
367+ ("red_min_threshold" , "166912" , "166913" , "replace" ),
368+ ("wred_green_enable" , "false" , "true" , "replace" ),
369+ ("wred_red_enable" , "false" , "true" , "replace" ),
370+ ("wred_yellow_enable" , "false" , "true" , "replace" ),
371+ ("yellow_drop_probability" , "5" , "6" , "replace" ),
372+ ("yellow_max_threshold" , "282624" , "282625" , "replace" ),
373+ ("yellow_min_threshold" , "166912" , "166913" , "replace" )
374+ ]
375+ )
376+ def test_validate_field_operation_wred_profile_replace (self , field , old_value , new_value , op ):
377+ old_config = {"WRED_PROFILE" : {"AZURE_LOSSY" : {field : old_value }}}
378+ target_config = {"WRED_PROFILE" : {"AZURE_LOSSY" : {field : new_value }}}
379+ config_wrapper = gu_common .ConfigWrapper ()
380+ config_wrapper .validate_field_operation (old_config , target_config )
381+
382+ @pytest .mark .parametrize (
383+ "field,value" , [
384+ ("green_min_threshold" , "1200" ),
385+ ("yellow_max_threshold" , "2400" ),
386+ ("red_min_threshold" , "3200" ),
387+ ("green_drop_probability" , "10" ),
388+ ("wred_green_enable" , "true" ),
389+ ("wred_yellow_enable" , "true" ),
390+ ("wred_red_enable" , "true" )
391+ ]
392+ )
393+ def test_validate_field_operation_wred_profile_add (self , field , value ):
394+ old_config = {"WRED_PROFILE" : {"AZURE_LOSSY" : {}}}
395+ target_config = {"WRED_PROFILE" : {"AZURE_LOSSY" : {field : value }}}
396+ config_wrapper = gu_common .ConfigWrapper ()
397+ config_wrapper .validate_field_operation (old_config , target_config )
398+
399+ @pytest .mark .parametrize (
400+ "table" , [
401+ "BUFFER_PORT_EGRESS_PROFILE_LIST" ,
402+ "BUFFER_PORT_INGRESS_PROFILE_LIST"
403+ ]
404+ )
405+ def test_validate_field_operation_buffer_port_profile_list_add (self , table ):
406+ old_config = {table : {"Ethernet0" : {}}}
407+ target_config = {table : {"Ethernet0" : {"profile_list" : "AZURE_PROFILE" }}}
408+ config_wrapper = gu_common .ConfigWrapper ()
409+ config_wrapper .validate_field_operation (old_config , target_config )
410+
411+ @pytest .mark .parametrize (
412+ "table" , [
413+ "BUFFER_PORT_EGRESS_PROFILE_LIST" ,
414+ "BUFFER_PORT_INGRESS_PROFILE_LIST"
415+ ]
416+ )
417+ def test_validate_field_operation_buffer_port_profile_list_replace (self , table ):
418+ old_config = {table : {"Ethernet0" : {"profile_list" : "AZURE_PROFILE" }}}
419+ target_config = {table : {"Ethernet0" : {"profile_list" : "NEW_PROFILE" }}}
420+ config_wrapper = gu_common .ConfigWrapper ()
421+ config_wrapper .validate_field_operation (old_config , target_config )
422+
423+ @pytest .mark .parametrize (
424+ "table" , [
425+ "BUFFER_PORT_EGRESS_PROFILE_LIST" ,
426+ "BUFFER_PORT_INGRESS_PROFILE_LIST"
427+ ]
428+ )
429+ def test_validate_field_operation_buffer_port_profile_list_remove (self , table ):
430+ old_config = {table : {"Ethernet0" : {"profile_list" : "AZURE_PROFILE" }}}
431+ target_config = {table : {"Ethernet0" : {}}}
432+ config_wrapper = gu_common .ConfigWrapper ()
433+ config_wrapper .validate_field_operation (old_config , target_config )
434+
435+ def test_validate_field_operation_queue_scheduler_replace (self ):
436+ old_config = {"QUEUE" : {"Ethernet0|0" : {"scheduler" : "sched0" }}}
437+ target_config = {"QUEUE" : {"Ethernet0|0" : {"scheduler" : "sched1" }}}
438+ config_wrapper = gu_common .ConfigWrapper ()
439+ config_wrapper .validate_field_operation (old_config , target_config )
440+
441+ def test_validate_field_operation_queue_wred_profile_add (self ):
442+ old_config = {"QUEUE" : {"Ethernet0|1" : {}}}
443+ target_config = {"QUEUE" : {"Ethernet0|1" : {"wred_profile" : "WRED_PROFILE" }}}
444+ config_wrapper = gu_common .ConfigWrapper ()
445+ config_wrapper .validate_field_operation (old_config , target_config )
446+
447+ def test_validate_field_operation_queue_wred_profile_replace (self ):
448+ old_config = {"QUEUE" : {"Ethernet0|1" : {"wred_profile" : "WRED_PROFILE" }}}
449+ target_config = {"QUEUE" : {"Ethernet0|1" : {"wred_profile" : "WRED_PROFILE_NEW" }}}
450+ config_wrapper = gu_common .ConfigWrapper ()
451+ config_wrapper .validate_field_operation (old_config , target_config )
452+
453+ @pytest .mark .parametrize (
454+ "field,new_value" , [
455+ ("dscp_to_tc_map" , "AZURE" ),
456+ ("tc_to_pg_map" , "AZURE" ),
457+ ("tc_to_queue_map" , "AZURE" )
458+ ]
459+ )
460+ def test_validate_field_operation_port_qos_map_replace (self , field , new_value ):
461+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {field : "DEFAULT" }}}
462+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {field : new_value }}}
463+ config_wrapper = gu_common .ConfigWrapper ()
464+ config_wrapper .validate_field_operation (old_config , target_config )
465+
466+ def test_validate_field_operation_port_qos_map_tc_to_dscp_add (self ):
467+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {}}}
468+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_dscp_map" : "AZURE" }}}
469+ config_wrapper = gu_common .ConfigWrapper ()
470+ config_wrapper .validate_field_operation (old_config , target_config )
471+
472+ def test_validate_field_operation_port_qos_map_tc_to_dscp_replace (self ):
473+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_dscp_map" : "DEFAULT" }}}
474+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_dscp_map" : "AZURE" }}}
475+ config_wrapper = gu_common .ConfigWrapper ()
476+ config_wrapper .validate_field_operation (old_config , target_config )
477+
478+ def test_validate_field_operation_port_qos_map_dscp_to_tc_replace (self ):
479+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"dscp_to_tc_map" : "DEFAULT" }}}
480+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"dscp_to_tc_map" : "AZURE" }}}
481+ config_wrapper = gu_common .ConfigWrapper ()
482+ config_wrapper .validate_field_operation (old_config , target_config )
483+
484+ def test_validate_field_operation_port_qos_map_tc_to_pg_replace (self ):
485+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_pg_map" : "DEFAULT" }}}
486+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_pg_map" : "AZURE" }}}
487+ config_wrapper = gu_common .ConfigWrapper ()
488+ config_wrapper .validate_field_operation (old_config , target_config )
489+
490+ def test_validate_field_operation_port_qos_map_tc_to_queue_replace (self ):
491+ old_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_queue_map" : "DEFAULT" }}}
492+ target_config = {"PORT_QOS_MAP" : {"Ethernet0" : {"tc_to_queue_map" : "AZURE" }}}
493+ config_wrapper = gu_common .ConfigWrapper ()
494+ config_wrapper .validate_field_operation (old_config , target_config )
495+
496+ def test_validate_field_operation_scheduler_weight_replace (self ):
497+ old_config = {"SCHEDULER" : {"scheduler.0" : {"weight" : "10" , "type" : "DWRR" }}}
498+ target_config = {"SCHEDULER" : {"scheduler.0" : {"weight" : "20" , "type" : "DWRR" }}}
499+ config_wrapper = gu_common .ConfigWrapper ()
500+ config_wrapper .validate_field_operation (old_config , target_config )
501+
502+
389503class TestGetAsicName (unittest .TestCase ):
390504
391505 @patch ('sonic_py_common.device_info.get_sonic_version_info' )
0 commit comments