STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_robustness_system.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""
3Comprehensive Test Suite for Robustness System
4Tests all validation, backup, health monitoring, and anomaly detection features.
5"""
6
7import sys
8import os
9import time
10import numpy as np
11import logging
12from pathlib import Path
13
14logging.basicConfig(
15 level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
16)
17logger = logging.getLogger(__name__)
18
19try:
20 from calibration_robustness import (
21 RobustnessManager,
22 SystemConfig,
23 OperationMode,
24 BackupManager,
25 CalibrationValidator,
26 HealthMonitor,
27 AnomalyDetector,
28 HealthMetrics,
29 )
30except ImportError as e:
31 logger.error(f"Cannot import robustness module: {e}")
32 sys.exit(1)
33
34
36 """Test configuration management"""
37 logger.info("\n" + "=" * 80)
38 logger.info("TEST 1: Configuration Management")
39 logger.info("=" * 80)
40
41 # Create and save config
42 config = SystemConfig()
43 config.mode = OperationMode.TEST
44 config.consensus_enabled = True
45 config.save("test_config.json")
46 logger.info("✓ Config saved")
47
48 # Load config
49 loaded_config = SystemConfig.load("test_config.json")
50 assert loaded_config.mode == OperationMode.TEST
51 assert loaded_config.consensus_enabled == True
52 logger.info("✓ Config loaded correctly")
53
54 # Cleanup
55 Path("test_config.json").unlink()
56 logger.info("✅ Configuration management test PASSED")
57
58
60 """Test backup and recovery system"""
61 logger.info("\n" + "=" * 80)
62 logger.info("TEST 2: Backup and Recovery")
63 logger.info("=" * 80)
64
65 config = SystemConfig()
66 config.backup_directory = "./test_backups"
67 backup_manager = BackupManager(config)
68
69 # Create test data (9 parameters for order=8)
70 population_prior = {
71 "population_mean": np.zeros(9).tolist(),
72 "population_covariance": np.diag([100.0] * 9).tolist(),
73 "population_strength": 5.0,
74 }
75
76 pt_states = {
77 0: {"mean": [0] * 9, "covariance": np.eye(9).tolist()},
78 1: {"mean": [0] * 9, "covariance": np.eye(9).tolist()},
79 }
80
81 metadata = {"test": True, "timestamp": time.time()}
82
83 # Backup
84 success = backup_manager.backup_calibration_state(
85 population_prior, pt_states, metadata
86 )
87 assert success, "Backup failed"
88 logger.info("✓ Backup created")
89
90 # List backups
91 backups = backup_manager.list_backups()
92 assert len(backups) > 0, "No backups found"
93 logger.info(f"✓ Found {len(backups)} backup(s)")
94
95 # Restore
96 restored = backup_manager.restore_latest_backup()
97 assert restored is not None, "Restore failed"
98 assert "population_prior" in restored
99 assert "pt_states" in restored
100 logger.info("✓ Backup restored")
101
102 # Verify data integrity
103 assert restored["population_prior"]["population_strength"] == 5.0
104 logger.info("✓ Data integrity verified")
105
106 # Cleanup
107 import shutil
108
109 shutil.rmtree("./test_backups")
110 logger.info("✅ Backup and recovery test PASSED")
111
112
114 """Test validation system"""
115 logger.info("\n" + "=" * 80)
116 logger.info("TEST 3: Validation System")
117 logger.info("=" * 80)
118
119 config = SystemConfig()
120 validator = CalibrationValidator(config)
121
122 # Test voltage validation
123 result = validator.validate_voltage(2.5, 0)
124 assert result.valid, "Valid voltage rejected"
125 logger.info("✓ Valid voltage accepted")
126
127 result = validator.validate_voltage(15.0, 0)
128 assert not result.valid, "Invalid voltage accepted"
129 logger.info("✓ Invalid voltage rejected")
130
131 result = validator.validate_voltage(np.nan, 0)
132 assert not result.valid, "NaN voltage accepted"
133 logger.info("✓ NaN voltage rejected")
134
135 # Test pressure validation
136 result = validator.validate_pressure(500.0, 0)
137 assert result.valid, "Valid pressure rejected"
138 logger.info("✓ Valid pressure accepted")
139
140 result = validator.validate_pressure(2000.0, 0)
141 assert not result.valid, "Invalid pressure accepted"
142 logger.info("✓ Invalid pressure rejected")
143
144 # Test coefficients validation (9 parameters for order=8)
145 coeffs = np.array([0, 200, 0, 0, 0, 0, 0, 0, 0])
146 result = validator.validate_calibration_coefficients(coeffs, 0)
147 assert result.valid, "Valid coefficients rejected"
148 logger.info("✓ Valid coefficients accepted")
149
150 coeffs_bad = np.array([0, 5000, 0, 0, 0, 0, 0, 0, 0]) # Unreasonable slope
151 result = validator.validate_calibration_coefficients(coeffs_bad, 0)
152 assert not result.valid, "Invalid coefficients accepted"
153 logger.info("✓ Invalid coefficients rejected")
154
155 # Test covariance validation (9x9 for order=8)
156 cov = np.eye(9) * 100
157 result = validator.validate_covariance_matrix(cov, 0)
158 assert result.valid, "Valid covariance rejected"
159 logger.info("✓ Valid covariance accepted")
160
161 cov_bad = np.diag([1, 1, 1, -1, 1, 1, 1, 1, 1]) # Not positive definite
162 result = validator.validate_covariance_matrix(cov_bad, 0)
163 assert not result.valid, "Invalid covariance accepted"
164 logger.info("✓ Invalid covariance rejected")
165
166 logger.info("✅ Validation system test PASSED")
167
168
170 """Test health monitoring system"""
171 logger.info("\n" + "=" * 80)
172 logger.info("TEST 4: Health Monitoring")
173 logger.info("=" * 80)
174
175 config = SystemConfig()
176 config.log_directory = "./test_logs"
177 health_monitor = HealthMonitor(config)
178
179 # Record some metrics
180 for i in range(5):
181 metrics = HealthMetrics(
182 timestamp=time.time(),
183 mode=OperationMode.TEST,
184 active_sensors=16,
185 calibrated_sensors=10 + i,
186 consensus_confidence=0.8 + i * 0.02,
187 average_uncertainty=5.0 - i * 0.5,
188 max_uncertainty=10.0 - i,
189 drift_detected_count=0,
190 validation_errors=0,
191 backup_status="OK",
192 uptime_seconds=i * 10.0,
193 )
194 health_monitor.record_metrics(metrics)
195 time.sleep(0.1)
196
197 logger.info("✓ Metrics recorded")
198
199 # Get status
200 status = health_monitor.get_current_status()
201 assert status["status"] in ("healthy", "degraded"), "Invalid status"
202 assert status["calibrated_sensors"] > 0, "No calibrated sensors"
203 logger.info(f"✓ System status: {status['status']}")
204
205 # Generate diagnostics
206 report = health_monitor.get_diagnostics_report()
207 assert len(report) > 0, "Empty diagnostics report"
208 logger.info("✓ Diagnostics report generated")
209 print("\n" + report)
210
211 # Cleanup
212 import shutil
213
214 if Path("./test_logs").exists():
215 shutil.rmtree("./test_logs")
216 logger.info("✅ Health monitoring test PASSED")
217
218
220 """Test anomaly detection system"""
221 logger.info("\n" + "=" * 80)
222 logger.info("TEST 5: Anomaly Detection")
223 logger.info("=" * 80)
224
225 config = SystemConfig()
226 anomaly_detector = AnomalyDetector(config)
227
228 # Feed normal data
229 for i in range(20):
230 voltage = 2.5 + np.random.normal(0, 0.01)
231 anomaly = anomaly_detector.detect_voltage_anomaly(0, voltage)
232 assert not anomaly, "Normal data flagged as anomaly"
233 logger.info("✓ Normal data accepted")
234
235 # Feed anomalous data
236 anomaly = anomaly_detector.detect_voltage_anomaly(0, 8.0) # Outlier
237 assert anomaly, "Anomaly not detected"
238 logger.info("✓ Voltage anomaly detected")
239
240 # Test pressure anomaly
241 for i in range(20):
242 pressure = 500.0 + np.random.normal(0, 1.0)
243 anomaly_detector.detect_pressure_anomaly(0, pressure)
244
245 # Rapid change
246 anomaly = anomaly_detector.detect_pressure_anomaly(0, 700.0) # +200 PSI jump
247 assert anomaly, "Pressure anomaly not detected"
248 logger.info("✓ Pressure anomaly detected")
249
250 # Get report
251 report = anomaly_detector.get_anomaly_report()
252 assert 0 in report, "Anomaly report missing sensor"
253 logger.info(f"✓ Anomaly counts: {report}")
254
255 logger.info("✅ Anomaly detection test PASSED")
256
257
259 """Test mode switching"""
260 logger.info("\n" + "=" * 80)
261 logger.info("TEST 6: Mode Switching")
262 logger.info("=" * 80)
263
264 manager = RobustnessManager()
265
266 # Test mode
267 manager.set_mode(OperationMode.TEST)
268 assert manager.config.mode == OperationMode.TEST
269 assert manager.config.consensus_enabled == True
270 logger.info("✓ TEST mode configured correctly")
271
272 # Flight mode
273 manager.set_mode(OperationMode.FLIGHT)
274 assert manager.config.mode == OperationMode.FLIGHT
275 assert manager.config.consensus_enabled == False
276 logger.info("✓ FLIGHT mode configured correctly (consensus DISABLED)")
277
278 # Calibration mode
279 manager.set_mode(OperationMode.CALIBRATION)
280 assert manager.config.mode == OperationMode.CALIBRATION
281 assert manager.config.consensus_enabled == True
282 logger.info("✓ CALIBRATION mode configured correctly")
283
284 # Safe mode
285 manager.set_mode(OperationMode.SAFE)
286 assert manager.config.mode == OperationMode.SAFE
287 logger.info("✓ SAFE mode configured correctly")
288
289 # Cleanup
290 Path("system_config.json").unlink(missing_ok=True)
291 logger.info("✅ Mode switching test PASSED")
292
293
295 """Test integrated robustness manager"""
296 logger.info("\n" + "=" * 80)
297 logger.info("TEST 7: Integrated Robustness Manager")
298 logger.info("=" * 80)
299
300 manager = RobustnessManager()
301
302 # Validate some data
303 v_result = manager.validator.validate_voltage(2.5, 0)
304 assert v_result.valid
305 logger.info("✓ Validation works")
306
307 # Check health monitoring
308 status = manager.health_monitor.get_current_status()
309 logger.info(f"✓ Health monitoring works: {status}")
310
311 # Test anomaly detection
312 anomaly = manager.anomaly_detector.detect_voltage_anomaly(0, 2.5)
313 logger.info(f"✓ Anomaly detection works: anomaly={anomaly}")
314
315 # Test mode control
316 manager.set_mode(OperationMode.TEST)
317 assert manager.config.consensus_enabled == True
318 manager.set_mode(OperationMode.FLIGHT)
319 assert manager.config.consensus_enabled == False
320 logger.info("✓ Mode control works")
321
322 # Cleanup
323 Path("system_config.json").unlink(missing_ok=True)
324 logger.info("✅ Integrated robustness manager test PASSED")
325
326
327def run_all_tests():
328 """Run all tests"""
329 print("\n" + "=" * 80)
330 print("ROBUSTNESS SYSTEM COMPREHENSIVE TEST SUITE")
331 print("=" * 80)
332
333 tests = [
334 ("Configuration Management", test_config_management),
335 ("Backup and Recovery", test_backup_and_recovery),
336 ("Validation System", test_validation),
337 ("Health Monitoring", test_health_monitoring),
338 ("Anomaly Detection", test_anomaly_detection),
339 ("Mode Switching", test_mode_switching),
340 ("Integrated Manager", test_integrated_robustness_manager),
341 ]
342
343 passed = 0
344 failed = 0
345
346 for name, test_func in tests:
347 try:
348 test_func()
349 passed += 1
350 except Exception as e:
351 logger.error(f"❌ {name} test FAILED: {e}")
352 import traceback
353
354 traceback.print_exc()
355 failed += 1
356
357 print("\n" + "=" * 80)
358 print("TEST SUMMARY")
359 print("=" * 80)
360 print(f"Total tests: {len(tests)}")
361 print(f"Passed: {passed} ✅")
362 print(f"Failed: {failed} ❌")
363 print(f"Success rate: {passed/len(tests)*100:.0f}%")
364 print("=" * 80 + "\n")
365
366 return failed == 0
367
368
369if __name__ == "__main__":
370 success = run_all_tests()
371 sys.exit(0 if success else 1)
TOML_NODISCARD_CTOR time() noexcept=default