1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script to validate ZPM package compilation without requiring IRIS admin access.
4
+ This script performs comprehensive validation of all ZPM package components.
5
+ """
6
+
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+ import xml .etree .ElementTree as ET
11
+
12
+ def test_module_xml ():
13
+ """Test module.xml structure and required elements."""
14
+ print ("π Testing module.xml structure..." )
15
+
16
+ module_xml = Path ("module.xml" )
17
+ if not module_xml .exists ():
18
+ print ("β module.xml not found" )
19
+ return False
20
+
21
+ try :
22
+ tree = ET .parse (module_xml )
23
+ root = tree .getroot ()
24
+
25
+ # Check required elements
26
+ required_elements = [
27
+ ".//Name" ,
28
+ ".//Version" ,
29
+ ".//Description" ,
30
+ ".//Dependencies" ,
31
+ ".//Packaging" ,
32
+ ".//Lifecycle"
33
+ ]
34
+
35
+ for element_path in required_elements :
36
+ element = root .find (element_path )
37
+ if element is None :
38
+ print (f"β Missing required element: { element_path } " )
39
+ return False
40
+
41
+ print ("β
module.xml structure is valid" )
42
+ return True
43
+
44
+ except ET .ParseError as e :
45
+ print (f"β module.xml parse error: { e } " )
46
+ return False
47
+
48
+ def test_objectscript_syntax ():
49
+ """Test ObjectScript class file syntax."""
50
+ print ("π Testing ObjectScript class syntax..." )
51
+
52
+ objectscript_dir = Path ("objectscript" )
53
+ if not objectscript_dir .exists ():
54
+ print ("β objectscript directory not found" )
55
+ return False
56
+
57
+ cls_files = list (objectscript_dir .rglob ("*.CLS" ))
58
+ if not cls_files :
59
+ print ("β No .CLS files found" )
60
+ return False
61
+
62
+ for cls_file in cls_files :
63
+ try :
64
+ rel_path = cls_file .relative_to (Path .cwd ())
65
+ except ValueError :
66
+ rel_path = cls_file
67
+ print (f" Checking { rel_path } " )
68
+
69
+ # Basic syntax checks
70
+ content = cls_file .read_text ()
71
+
72
+ # Check for basic ObjectScript class structure
73
+ if not content .startswith ("///" ) and "Class " not in content :
74
+ print (f"β { cls_file .name } : Missing class declaration" )
75
+ return False
76
+
77
+ # Check for balanced braces (simple check)
78
+ open_braces = content .count ("{" )
79
+ close_braces = content .count ("}" )
80
+ if open_braces != close_braces :
81
+ print (f"β { cls_file .name } : Unbalanced braces ({ open_braces } open, { close_braces } close)" )
82
+ return False
83
+
84
+ # Enhanced brace validation - check for problematic patterns that cause compilation errors
85
+ lines = content .split ('\n ' )
86
+ brace_stack = []
87
+
88
+ for i , line in enumerate (lines , 1 ):
89
+ stripped = line .strip ()
90
+
91
+ # Track brace context for better validation
92
+ if '{' in line :
93
+ brace_stack .append (i )
94
+ if '}' in line and brace_stack :
95
+ brace_stack .pop ()
96
+
97
+ # Only flag truly suspicious patterns - consecutive closing braces at same indentation level
98
+ # that don't correspond to nested structures
99
+ if (stripped == '}' and i < len (lines ) - 1 ):
100
+ next_line = lines [i ].strip () if i < len (lines ) else ""
101
+ if next_line == '}' :
102
+ # Check indentation to see if these are at the same level (suspicious)
103
+ current_indent = len (line ) - len (line .lstrip ())
104
+ next_indent = len (lines [i ]) - len (lines [i ].lstrip ()) if i < len (lines ) else 0
105
+
106
+ # Flag only if same indentation (likely error) and not in obvious nested context
107
+ if current_indent == next_indent and current_indent == 0 :
108
+ print (f"β { cls_file .name } : Suspicious consecutive closing braces at same indentation at lines { i } and { i + 1 } " )
109
+ print (f" Line { i } : '{ line } '" )
110
+ print (f" Line { i + 1 } : '{ next_line } '" )
111
+ return False
112
+
113
+ print (f"β
All { len (cls_files )} ObjectScript files have valid syntax" )
114
+ return True
115
+
116
+ def test_ipm_validators ():
117
+ """Run the IPM package validators."""
118
+ print ("π Running IPM package validators..." )
119
+
120
+ # Test basic IPM package validator
121
+ try :
122
+ result = subprocess .run ([
123
+ sys .executable , "scripts/validate_ipm_package.py" , "."
124
+ ], capture_output = True , text = True , timeout = 30 )
125
+
126
+ if result .returncode != 0 :
127
+ print ("β Basic IPM package validation failed" )
128
+ print ("STDOUT:" , result .stdout )
129
+ print ("STDERR:" , result .stderr )
130
+ return False
131
+
132
+ if "β
IPM package validation PASSED" not in result .stdout :
133
+ print ("β Basic IPM package validation did not pass" )
134
+ return False
135
+
136
+ except subprocess .TimeoutExpired :
137
+ print ("β Basic IPM package validator timed out" )
138
+ return False
139
+ except Exception as e :
140
+ print (f"β Error running basic IPM validator: { e } " )
141
+ return False
142
+
143
+ # Test comprehensive IPM module validator
144
+ try :
145
+ result = subprocess .run ([
146
+ sys .executable , "scripts/utilities/validate_ipm_module.py" ,
147
+ "--project-root" , "."
148
+ ], capture_output = True , text = True , timeout = 30 )
149
+
150
+ if result .returncode != 0 :
151
+ print ("β Comprehensive IPM module validation failed" )
152
+ print ("STDOUT:" , result .stdout )
153
+ print ("STDERR:" , result .stderr )
154
+ return False
155
+
156
+ if "β
PASSED" not in result .stdout :
157
+ print ("β Comprehensive IPM module validation did not pass" )
158
+ return False
159
+
160
+ except subprocess .TimeoutExpired :
161
+ print ("β Comprehensive IPM module validator timed out" )
162
+ return False
163
+ except Exception as e :
164
+ print (f"β Error running comprehensive IPM validator: { e } " )
165
+ return False
166
+
167
+ print ("β
All IPM validators passed" )
168
+ return True
169
+
170
+ def test_python_package_structure ():
171
+ """Test Python package structure."""
172
+ print ("π Testing Python package structure..." )
173
+
174
+ required_packages = ["iris_rag" , "rag_templates" , "common" ]
175
+
176
+ for package in required_packages :
177
+ package_path = Path (package )
178
+ if not package_path .exists ():
179
+ print (f"β Missing Python package: { package } " )
180
+ return False
181
+
182
+ init_file = package_path / "__init__.py"
183
+ if not init_file .exists ():
184
+ print (f"β Missing __init__.py in { package } " )
185
+ return False
186
+
187
+ print (f"β
All { len (required_packages )} Python packages are valid" )
188
+ return True
189
+
190
+ def main ():
191
+ """Run all ZPM compilation tests."""
192
+ print ("π§ͺ ZPM Package Compilation Test" )
193
+ print ("=" * 50 )
194
+
195
+ tests = [
196
+ ("Module XML Structure" , test_module_xml ),
197
+ ("ObjectScript Syntax" , test_objectscript_syntax ),
198
+ ("Python Package Structure" , test_python_package_structure ),
199
+ ("IPM Validators" , test_ipm_validators ),
200
+ ]
201
+
202
+ passed = 0
203
+ total = len (tests )
204
+
205
+ for test_name , test_func in tests :
206
+ print (f"\n π { test_name } " )
207
+ try :
208
+ if test_func ():
209
+ passed += 1
210
+ else :
211
+ print (f"β { test_name } FAILED" )
212
+ except Exception as e :
213
+ print (f"β { test_name } ERROR: { e } " )
214
+
215
+ print ("\n " + "=" * 50 )
216
+ print (f"π― Results: { passed } /{ total } tests passed" )
217
+
218
+ if passed == total :
219
+ print ("π ZPM package compilation test PASSED" )
220
+ print ("β
Package is ready for deployment" )
221
+ return 0
222
+ else :
223
+ print ("β ZPM package compilation test FAILED" )
224
+ print ("π§ Please fix the issues above before deployment" )
225
+ return 1
226
+
227
+ if __name__ == "__main__" :
228
+ sys .exit (main ())
0 commit comments