55
66class TestFixModulesArgs (TestCase ):
77
8- # 1. Single key-value pair string
8+ # 1. Single key-value pair string, no defaults - kept as single string
99 def test_single_key_value_pair (self ):
1010 result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4' )
1111 self .assertEqual (result , [['WORKERS 4' ]])
1212
13- # 2. Multiple key-value pairs without semicolons (new behavior)
14- def test_multiple_kv_pairs_no_semicolons (self ):
13+ # 2. Multiple key-value pairs without semicolons, no defaults - kept as single string
14+ def test_multiple_kv_pairs_no_semicolons_no_defaults (self ):
1515 result = fix_modulesArgs (['/mod.so' ], '_FREE_RESOURCE_ON_THREAD FALSE TIMEOUT 80 WORKERS 4' )
16- self .assertEqual (result , [['_FREE_RESOURCE_ON_THREAD FALSE' , ' TIMEOUT 80' , ' WORKERS 4' ]])
16+ self .assertEqual (result , [['_FREE_RESOURCE_ON_THREAD FALSE TIMEOUT 80 WORKERS 4' ]])
1717
1818 # 3. Semicolon-separated args (existing behavior)
1919 def test_semicolon_separated_args (self ):
2020 result = fix_modulesArgs (['/mod.so' ], 'KEY1 V1; KEY2 V2' )
2121 self .assertEqual (result , [['KEY1 V1' , 'KEY2 V2' ]])
2222
23- # 4a . Odd number of words without semicolons - should error
24- def test_odd_words_no_semicolons_exits (self ):
25- with self . assertRaises ( SystemExit ):
26- fix_modulesArgs ([ '/mod.so' ], 'FLAG TIMEOUT 80' )
23+ # 4 . Odd number of words without semicolons, no defaults - kept as single string, no error
24+ def test_odd_words_no_semicolons_no_error (self ):
25+ result = fix_modulesArgs ([ '/mod.so' ], 'FLAG TIMEOUT 80 ' )
26+ self . assertEqual ( result , [[ 'FLAG TIMEOUT 80' ]] )
2727
2828 # 4b. Odd number of words with semicolons - valid, semicolons split first
2929 def test_odd_words_with_semicolons_valid (self ):
3030 result = fix_modulesArgs (['/mod.so' ], 'FLAG; TIMEOUT 80' )
3131 self .assertEqual (result , [['FLAG' , 'TIMEOUT 80' ]])
3232
33- # 5a. Space-separated string overrides matching defaults, non-matching defaults added
34- def test_space_separated_overrides_defaults (self ):
33+ # 5a. Plain string with defaults - word-based merge, missing defaults appended
34+ def test_plain_string_overrides_defaults (self ):
3535 defaults = [['WORKERS 8' , 'TIMEOUT 60' , 'EXTRA 1' ]]
3636 result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4 TIMEOUT 80' , defaults )
37- result_dict = {arg .split (' ' )[0 ]: arg for arg in result [0 ]}
38- self .assertEqual (result_dict ['WORKERS' ], 'WORKERS 4' )
39- self .assertEqual (result_dict ['TIMEOUT' ], 'TIMEOUT 80' )
40- self .assertEqual (result_dict ['EXTRA' ], 'EXTRA 1' )
37+ # Result is a single merged string
38+ self .assertEqual (result , [['WORKERS 4 TIMEOUT 80 EXTRA 1' ]])
4139
42- # 5b. Semicolon-separated string overrides matching defaults
40+ # 5b. Semicolon-separated string overrides matching defaults (dict-based merge)
4341 def test_semicolon_separated_overrides_defaults (self ):
4442 defaults = [['WORKERS 8' , 'TIMEOUT 60' , 'EXTRA 1' ]]
4543 result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4; TIMEOUT 80' , defaults )
@@ -48,14 +46,11 @@ def test_semicolon_separated_overrides_defaults(self):
4846 self .assertEqual (result_dict ['TIMEOUT' ], 'TIMEOUT 80' )
4947 self .assertEqual (result_dict ['EXTRA' ], 'EXTRA 1' )
5048
51- # 5c. Space-separated explicit overrides some defaults, non-overlapping defaults are merged
52- def test_space_separated_partial_override_with_defaults (self ):
49+ # 5c. Plain string partial override - missing defaults appended
50+ def test_plain_string_partial_override_with_defaults (self ):
5351 defaults = [['_FREE_RESOURCE_ON_THREAD TRUE' , 'TIMEOUT 100' , 'WORKERS 8' ]]
5452 result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4 TIMEOUT 80' , defaults )
55- result_dict = {arg .split (' ' )[0 ]: arg for arg in result [0 ]}
56- self .assertEqual (result_dict ['WORKERS' ], 'WORKERS 4' )
57- self .assertEqual (result_dict ['TIMEOUT' ], 'TIMEOUT 80' )
58- self .assertEqual (result_dict ['_FREE_RESOURCE_ON_THREAD' ], '_FREE_RESOURCE_ON_THREAD TRUE' )
53+ self .assertEqual (result , [['WORKERS 4 TIMEOUT 80 _FREE_RESOURCE_ON_THREAD TRUE' ]])
5954
6055 # 6. None input with defaults - deep copy of defaults
6156 def test_none_uses_defaults (self ):
@@ -66,7 +61,7 @@ def test_none_uses_defaults(self):
6661 result [0 ][0 ] = 'MODIFIED'
6762 self .assertEqual (defaults [0 ][0 ], 'WORKERS 8' )
6863
69- # 7. List of strings with defaults - overlapping and non-overlapping keys
64+ # 7. List of strings with defaults - dict-based merge
7065 def test_list_of_strings_with_defaults (self ):
7166 defaults = [['K1 default1' , 'K2 default2' , 'K4 default4' ]]
7267 result = fix_modulesArgs (['/mod.so' ], ['K1 override1' , 'K2 override2' , 'K3 new3' ], defaults )
@@ -76,35 +71,40 @@ def test_list_of_strings_with_defaults(self):
7671 self .assertEqual (result_dict ['K3' ], 'K3 new3' )
7772 self .assertEqual (result_dict ['K4' ], 'K4 default4' )
7873
79- # 8. List of lists (multi-module) with defaults - overlapping and non-overlapping keys
74+ # 8. List of lists (multi-module) with defaults - dict-based merge
8075 def test_multi_module_with_defaults (self ):
8176 modules = ['/mod1.so' , '/mod2.so' ]
8277 explicit = [['K1 v1' , 'K2 v2' ], ['K3 v3' ]]
8378 defaults = [['K1 d1' , 'K5 d5' ], ['K3 d3' , 'K4 d4' ]]
8479 result = fix_modulesArgs (modules , explicit , defaults )
85- # Module 1: K1 overridden, K5 added from defaults
8680 dict1 = {arg .split (' ' )[0 ]: arg for arg in result [0 ]}
8781 self .assertEqual (dict1 ['K1' ], 'K1 v1' )
8882 self .assertEqual (dict1 ['K2' ], 'K2 v2' )
8983 self .assertEqual (dict1 ['K5' ], 'K5 d5' )
90- # Module 2: K3 overridden, K4 added from defaults
9184 dict2 = {arg .split (' ' )[0 ]: arg for arg in result [1 ]}
9285 self .assertEqual (dict2 ['K3' ], 'K3 v3' )
9386 self .assertEqual (dict2 ['K4' ], 'K4 d4' )
9487
88+ # 9. Odd words with defaults - word-based merge, flags and multi-value args handled
89+ def test_odd_words_with_defaults (self ):
90+ defaults = [['FORK_GC_CLEAN_NUMERIC_EMPTY_NODES' , 'TIMEOUT 90' ]]
91+ result = fix_modulesArgs (['/mod.so' ], 'workers 0 nogc FORK_GC_CLEAN_NUMERIC_EMPTY_NODES timeout 90' , defaults )
92+ self .assertEqual (result , [['workers 0 nogc FORK_GC_CLEAN_NUMERIC_EMPTY_NODES timeout 90' ]])
9593
96- # 9. Case-insensitive matching between explicit args and defaults (both directions)
97- def test_case_insensitive_override (self ):
98- # Uppercase explicit overrides lowercase defaults
99- defaults = [['workers 8' , 'timeout 60' , 'EXTRA 1' , 'MIxEd 7' , 'lower true' ]]
100- result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4 TIMEOUT 80 miXed 0 LOWER false' , defaults )
101- result_dict = {arg .split (' ' )[0 ]: arg for arg in result [0 ]}
102- self .assertEqual (result_dict ['WORKERS' ], 'WORKERS 4' )
103- self .assertEqual (result_dict ['TIMEOUT' ], 'TIMEOUT 80' )
104- self .assertEqual (result_dict ['EXTRA' ], 'EXTRA 1' )
105- self .assertEqual (result_dict ['miXed' ], 'miXed 0' )
106- self .assertEqual (result_dict ['LOWER' ], 'LOWER false' )
107- self .assertNotIn ('workers' , result_dict )
108- self .assertNotIn ('timeout' , result_dict )
109- self .assertNotIn ('MIxEd' , result_dict )
110- self .assertNotIn ('lower' , result_dict )
94+ # 10. Plain string with defaults - unknown keys not in defaults stay, missing defaults appended
95+ def test_plain_string_new_keys_with_defaults (self ):
96+ defaults = [['TIMEOUT 60' ]]
97+ result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4 TIMEOUT 80' , defaults )
98+ self .assertEqual (result , [['WORKERS 4 TIMEOUT 80' ]])
99+
100+ # 11. Case-insensitive word matching for plain string merge
101+ def test_case_insensitive_word_merge (self ):
102+ defaults = [['workers 8' , 'TIMEOUT 60' , 'EXTRA 1' ]]
103+ result = fix_modulesArgs (['/mod.so' ], 'WORKERS 4 timeout 80' , defaults )
104+ self .assertEqual (result , [['WORKERS 4 timeout 80 EXTRA 1' ]])
105+
106+ # 12. Substring key should not falsely match (GC should not match nogc)
107+ def test_no_substring_match (self ):
108+ defaults = [['GC enabled' ]]
109+ result = fix_modulesArgs (['/mod.so' ], 'nogc TIMEOUT 80' , defaults )
110+ self .assertEqual (result , [['nogc TIMEOUT 80 GC enabled' ]])
0 commit comments