55Validates JSON schema, regex syntax, i18n completeness, and metadata.
66
77Run: pytest tests/test_pattern_validation.py -v
8+
9+ ═══════════════════════════════════════════════════════════════════════════
10+ ⚠️ CRITICAL: Field Name Consistency Warning
11+ ═══════════════════════════════════════════════════════════════════════════
12+ This test suite validates JSON pattern files against the schema.
13+
14+ IMPORTANT: JSON Schema Field Names (DO NOT CHANGE):
15+ - patterns/schema.json uses "regex" (NOT "pattern")
16+ - patterns/schema.json uses "error_key" (NOT "suggestion_key")
17+
18+ Common Mistake:
19+ ❌ required_fields = ["id", "pattern", "suggestion_key", ...]
20+ ✅ required_fields = ["id", "regex", "error_key", ...]
21+
22+ If tests fail with "missing required field", check that test expectations
23+ match the actual schema definition in patterns/schema.json.
24+
25+ Last Modified: 2026-01-03 (Fixed field name mismatch)
26+ ═══════════════════════════════════════════════════════════════════════════
827"""
928
1029import json
@@ -51,28 +70,34 @@ def load_pattern_file(file_path: Path) -> Dict:
5170 return json .load (f )
5271
5372
54- def extract_error_keys_from_i18n () -> Set [str ]:
55- """Extract all ERROR_KEYS from i18n.py"""
73+ def extract_error_keys_from_i18n () -> Dict [str , str ]:
74+ """
75+ Extract ERROR_KEYS mapping from i18n.py.
76+
77+ Returns:
78+ Dict mapping uppercase keys to lowercase suggestion keys.
79+ Example: {"TYPE_MISMATCH": "type_mismatch", "CUDNN_ERROR": "cudnn_error", ...}
80+ """
5681 with open (I18N_PATH , "r" , encoding = "utf-8" ) as f :
5782 content = f .read ()
58-
83+
5984 # Find ERROR_KEYS dictionary
60- start = content .find ("ERROR_KEYS" )
85+ start = content .find ("ERROR_KEYS = { " )
6186 if start == - 1 :
62- return set ()
63-
64- # Extract keys (simplified parsing)
65- keys = set ()
87+ return {}
88+
89+ # Extract key-value pairs (simplified parsing)
90+ error_keys_dict = {}
6691 lines = content [start :].split ("\n " )
6792 for line in lines :
6893 if '"' in line and ":" in line :
69- # Extract key from line like: "oom ": "oom ",
70- match = re .search (r'"([^"]+)":\s*"' , line )
94+ # Extract key-value from line like: "TYPE_MISMATCH ": "type_mismatch ",
95+ match = re .search (r'"([^"]+)":\s*"([^"]+)" ' , line )
7196 if match :
72- keys . add ( match .group (1 ))
97+ error_keys_dict [ match .group (1 )] = match . group ( 2 )
7398 if line .strip () == "}" :
7499 break
75- return keys
100+ return error_keys_dict
76101
77102
78103def extract_suggestions_from_i18n () -> Dict [str , Set [str ]]:
@@ -152,8 +177,11 @@ def test_all_patterns_valid_json(self):
152177
153178 def test_all_patterns_have_required_fields (self , all_patterns ):
154179 """Test 2: All patterns have required fields"""
155- required_fields = ["id" , "pattern" , "priority" , "category" , "suggestion_key" ]
156-
180+ # ⚠️ CRITICAL: These field names MUST match patterns/schema.json
181+ # DO NOT change "regex" to "pattern" or "error_key" to "suggestion_key"
182+ # See file docstring for detailed explanation
183+ required_fields = ["id" , "regex" , "error_key" , "priority" , "category" ]
184+
157185 for pattern in all_patterns :
158186 for field in required_fields :
159187 assert field in pattern , (
@@ -165,43 +193,46 @@ def test_all_regex_compile(self, all_patterns):
165193 """Test 3: All regex patterns compile successfully"""
166194 for pattern in all_patterns :
167195 pattern_id = pattern .get ("id" , "UNKNOWN" )
168- regex_str = pattern .get ("pattern" , "" )
169-
196+ # ⚠️ CRITICAL: Use "regex" (schema field name), NOT "pattern"
197+ regex_str = pattern .get ("regex" , "" )
198+
170199 try :
171200 re .compile (regex_str )
172201 except re .error as e :
173202 pytest .fail (
174203 f"Pattern { pattern_id } in { pattern ['_source_file' ]} "
175204 f"has invalid regex: { e } "
176205 )
177-
206+
178207 def test_all_suggestions_exist (self , all_patterns , error_keys , suggestions ):
179- """Test 4: All suggestion_key values exist in i18n.py"""
208+ """Test 4: All error_key values exist in i18n.py ERROR_KEYS and SUGGESTIONS """
180209 # Check ERROR_KEYS mapping
181210 for pattern in all_patterns :
182211 pattern_id = pattern .get ("id" , "UNKNOWN" )
183- suggestion_key = pattern .get ("suggestion_key" , "" )
184-
185- assert suggestion_key in error_keys , (
212+ # ⚠️ CRITICAL: Use "error_key" (schema field name), NOT "suggestion_key"
213+ error_key = pattern .get ("error_key" , "" )
214+
215+ assert error_key in error_keys , (
186216 f"Pattern { pattern_id } in { pattern ['_source_file' ]} "
187- f"has suggestion_key '{ suggestion_key } ' not found in ERROR_KEYS"
217+ f"has error_key '{ error_key } ' not found in ERROR_KEYS"
188218 )
189-
219+
190220 # Check all languages have translations
191221 for lang in SUPPORTED_LANGUAGES :
192222 assert lang in suggestions , f"Language '{ lang } ' not found in SUGGESTIONS"
193-
223+
194224 for pattern in all_patterns :
195225 pattern_id = pattern .get ("id" , "UNKNOWN" )
196- suggestion_key = pattern .get ("suggestion_key" , "" )
197-
198- # Map through ERROR_KEYS to get the actual key
199- if suggestion_key in error_keys :
200- # For simplicity, assume suggestion_key IS the final key
201- # (in reality, ERROR_KEYS maps pattern keys to suggestion keys)
202- assert suggestion_key in suggestions [lang ], (
203- f"Pattern { pattern_id } missing { lang } translation for '{ suggestion_key } '"
204- )
226+ error_key = pattern .get ("error_key" , "" )
227+
228+ # Get the suggestion key from ERROR_KEYS mapping
229+ # Example: error_key="CUDNN_ERROR" -> suggestion_key="cudnn_error"
230+ suggestion_key = error_keys .get (error_key , "" )
231+
232+ assert suggestion_key in suggestions [lang ], (
233+ f"Pattern { pattern_id } (error_key: { error_key } ) missing { lang } translation. "
234+ f"Expected suggestion key '{ suggestion_key } ' in SUGGESTIONS['{ lang } ']"
235+ )
205236
206237 def test_priority_ranges (self , all_patterns ):
207238 """Test 5: All priorities are within valid range 50-95"""
0 commit comments