zexus 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ZPICS Evaluator - Runtime Behavior Validation
|
|
3
|
+
==============================================
|
|
4
|
+
|
|
5
|
+
Extension of ZPICS that validates runtime behavior (evaluator) in addition to parse trees.
|
|
6
|
+
Ensures that code changes don't break expected runtime results.
|
|
7
|
+
|
|
8
|
+
Author: Zexus Team
|
|
9
|
+
Date: December 2025
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import hashlib
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Dict, List, Optional, Any, Tuple
|
|
17
|
+
from dataclasses import dataclass, asdict
|
|
18
|
+
from io import StringIO
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ExecutionSnapshot:
|
|
23
|
+
"""Represents a snapshot of code execution"""
|
|
24
|
+
source_code: str
|
|
25
|
+
source_hash: str
|
|
26
|
+
stdout_output: str
|
|
27
|
+
stderr_output: str
|
|
28
|
+
exit_code: int
|
|
29
|
+
execution_metadata: Dict[str, Any]
|
|
30
|
+
variables_final: Dict[str, str] # Final variable values (as strings)
|
|
31
|
+
execution_time_ms: float
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
34
|
+
"""Convert to dictionary for JSON serialization"""
|
|
35
|
+
return asdict(self)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'ExecutionSnapshot':
|
|
39
|
+
"""Create from dictionary"""
|
|
40
|
+
return cls(**data)
|
|
41
|
+
|
|
42
|
+
def fingerprint(self) -> str:
|
|
43
|
+
"""Generate unique fingerprint for this execution result"""
|
|
44
|
+
fp_data = {
|
|
45
|
+
'source_hash': self.source_hash,
|
|
46
|
+
'stdout': self.stdout_output,
|
|
47
|
+
'exit_code': self.exit_code,
|
|
48
|
+
'variables': sorted(self.variables_final.items())
|
|
49
|
+
}
|
|
50
|
+
fp_str = json.dumps(fp_data, sort_keys=True)
|
|
51
|
+
return hashlib.sha256(fp_str.encode()).hexdigest()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass
|
|
55
|
+
class RuntimeViolation:
|
|
56
|
+
"""Represents a detected runtime behavior violation"""
|
|
57
|
+
test_name: str
|
|
58
|
+
violation_type: str
|
|
59
|
+
expected: Any
|
|
60
|
+
actual: Any
|
|
61
|
+
severity: str # 'critical', 'warning', 'info'
|
|
62
|
+
description: str
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ZPICSEvaluatorValidator:
|
|
66
|
+
"""Validator for runtime behavior invariants"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, snapshot_dir: str = ".zpics_runtime"):
|
|
69
|
+
self.snapshot_dir = Path(snapshot_dir)
|
|
70
|
+
self.snapshot_dir.mkdir(exist_ok=True)
|
|
71
|
+
self.violations: List[RuntimeViolation] = []
|
|
72
|
+
|
|
73
|
+
def create_snapshot(self, test_name: str, source_code: str) -> ExecutionSnapshot:
|
|
74
|
+
"""
|
|
75
|
+
Create an execution snapshot by running the code
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
test_name: Name of the test case
|
|
79
|
+
source_code: The Zexus code to execute
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
ExecutionSnapshot object
|
|
83
|
+
"""
|
|
84
|
+
import time
|
|
85
|
+
from zexus.lexer import Lexer
|
|
86
|
+
from zexus.parser import Parser
|
|
87
|
+
from zexus.evaluator import Evaluator
|
|
88
|
+
from zexus.object import Environment
|
|
89
|
+
|
|
90
|
+
# Hash the source code
|
|
91
|
+
source_hash = hashlib.md5(source_code.encode()).hexdigest()
|
|
92
|
+
|
|
93
|
+
# Capture stdout/stderr
|
|
94
|
+
old_stdout = sys.stdout
|
|
95
|
+
old_stderr = sys.stderr
|
|
96
|
+
stdout_capture = StringIO()
|
|
97
|
+
stderr_capture = StringIO()
|
|
98
|
+
|
|
99
|
+
exit_code = 0
|
|
100
|
+
variables_final = {}
|
|
101
|
+
execution_time = 0.0
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
sys.stdout = stdout_capture
|
|
105
|
+
sys.stderr = stderr_capture
|
|
106
|
+
|
|
107
|
+
start_time = time.time()
|
|
108
|
+
|
|
109
|
+
# Parse and evaluate
|
|
110
|
+
lexer = Lexer(source_code)
|
|
111
|
+
tokens = lexer.tokenize()
|
|
112
|
+
parser = Parser()
|
|
113
|
+
ast = parser.parse(tokens)
|
|
114
|
+
|
|
115
|
+
env = Environment()
|
|
116
|
+
evaluator = Evaluator()
|
|
117
|
+
evaluator.eval(ast, env)
|
|
118
|
+
|
|
119
|
+
execution_time = (time.time() - start_time) * 1000 # ms
|
|
120
|
+
|
|
121
|
+
# Extract final variable states
|
|
122
|
+
if hasattr(env, 'store'):
|
|
123
|
+
for var_name, var_value in env.store.items():
|
|
124
|
+
# Skip internal/builtin variables
|
|
125
|
+
if not var_name.startswith('_'):
|
|
126
|
+
variables_final[var_name] = str(var_value)
|
|
127
|
+
|
|
128
|
+
except SystemExit as e:
|
|
129
|
+
exit_code = e.code if e.code else 0
|
|
130
|
+
except Exception as e:
|
|
131
|
+
exit_code = 1
|
|
132
|
+
stderr_capture.write(f"Error: {str(e)}\n")
|
|
133
|
+
finally:
|
|
134
|
+
sys.stdout = old_stdout
|
|
135
|
+
sys.stderr = old_stderr
|
|
136
|
+
|
|
137
|
+
stdout_output = stdout_capture.getvalue()
|
|
138
|
+
stderr_output = stderr_capture.getvalue()
|
|
139
|
+
|
|
140
|
+
return ExecutionSnapshot(
|
|
141
|
+
source_code=source_code,
|
|
142
|
+
source_hash=source_hash,
|
|
143
|
+
stdout_output=stdout_output,
|
|
144
|
+
stderr_output=stderr_output,
|
|
145
|
+
exit_code=exit_code,
|
|
146
|
+
execution_metadata={
|
|
147
|
+
'test_name': test_name
|
|
148
|
+
},
|
|
149
|
+
variables_final=variables_final,
|
|
150
|
+
execution_time_ms=execution_time
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def save_snapshot(self, test_name: str, snapshot: ExecutionSnapshot):
|
|
154
|
+
"""Save snapshot to disk"""
|
|
155
|
+
snapshot_file = self.snapshot_dir / f"{test_name}.json"
|
|
156
|
+
with open(snapshot_file, 'w') as f:
|
|
157
|
+
json.dump(snapshot.to_dict(), f, indent=2)
|
|
158
|
+
|
|
159
|
+
def load_snapshot(self, test_name: str) -> Optional[ExecutionSnapshot]:
|
|
160
|
+
"""Load snapshot from disk"""
|
|
161
|
+
snapshot_file = self.snapshot_dir / f"{test_name}.json"
|
|
162
|
+
if not snapshot_file.exists():
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
with open(snapshot_file, 'r') as f:
|
|
166
|
+
data = json.load(f)
|
|
167
|
+
return ExecutionSnapshot.from_dict(data)
|
|
168
|
+
|
|
169
|
+
def validate_snapshot(self, test_name: str, current: ExecutionSnapshot,
|
|
170
|
+
baseline: ExecutionSnapshot) -> List[RuntimeViolation]:
|
|
171
|
+
"""
|
|
172
|
+
Validate current execution against baseline snapshot
|
|
173
|
+
|
|
174
|
+
Returns list of violations found
|
|
175
|
+
"""
|
|
176
|
+
violations = []
|
|
177
|
+
|
|
178
|
+
# Check stdout output
|
|
179
|
+
if current.stdout_output.strip() != baseline.stdout_output.strip():
|
|
180
|
+
violations.append(RuntimeViolation(
|
|
181
|
+
test_name=test_name,
|
|
182
|
+
violation_type='stdout_changed',
|
|
183
|
+
expected=baseline.stdout_output,
|
|
184
|
+
actual=current.stdout_output,
|
|
185
|
+
severity='critical',
|
|
186
|
+
description='Program output has changed'
|
|
187
|
+
))
|
|
188
|
+
|
|
189
|
+
# Check exit code
|
|
190
|
+
if current.exit_code != baseline.exit_code:
|
|
191
|
+
violations.append(RuntimeViolation(
|
|
192
|
+
test_name=test_name,
|
|
193
|
+
violation_type='exit_code_changed',
|
|
194
|
+
expected=baseline.exit_code,
|
|
195
|
+
actual=current.exit_code,
|
|
196
|
+
severity='critical',
|
|
197
|
+
description=f'Exit code changed from {baseline.exit_code} to {current.exit_code}'
|
|
198
|
+
))
|
|
199
|
+
|
|
200
|
+
# Check final variables
|
|
201
|
+
baseline_vars = set(baseline.variables_final.keys())
|
|
202
|
+
current_vars = set(current.variables_final.keys())
|
|
203
|
+
|
|
204
|
+
missing_vars = baseline_vars - current_vars
|
|
205
|
+
extra_vars = current_vars - baseline_vars
|
|
206
|
+
|
|
207
|
+
if missing_vars:
|
|
208
|
+
violations.append(RuntimeViolation(
|
|
209
|
+
test_name=test_name,
|
|
210
|
+
violation_type='missing_variables',
|
|
211
|
+
expected=list(baseline_vars),
|
|
212
|
+
actual=list(current_vars),
|
|
213
|
+
severity='critical',
|
|
214
|
+
description=f'Variables missing after execution: {missing_vars}'
|
|
215
|
+
))
|
|
216
|
+
|
|
217
|
+
if extra_vars:
|
|
218
|
+
violations.append(RuntimeViolation(
|
|
219
|
+
test_name=test_name,
|
|
220
|
+
violation_type='extra_variables',
|
|
221
|
+
expected=list(baseline_vars),
|
|
222
|
+
actual=list(current_vars),
|
|
223
|
+
severity='warning',
|
|
224
|
+
description=f'Extra variables after execution: {extra_vars}'
|
|
225
|
+
))
|
|
226
|
+
|
|
227
|
+
# Check variable values for common variables
|
|
228
|
+
common_vars = baseline_vars & current_vars
|
|
229
|
+
for var_name in common_vars:
|
|
230
|
+
if baseline.variables_final[var_name] != current.variables_final[var_name]:
|
|
231
|
+
violations.append(RuntimeViolation(
|
|
232
|
+
test_name=test_name,
|
|
233
|
+
violation_type='variable_value_changed',
|
|
234
|
+
expected=f"{var_name}={baseline.variables_final[var_name]}",
|
|
235
|
+
actual=f"{var_name}={current.variables_final[var_name]}",
|
|
236
|
+
severity='critical',
|
|
237
|
+
description=f'Variable {var_name} value changed'
|
|
238
|
+
))
|
|
239
|
+
|
|
240
|
+
# Check execution fingerprint
|
|
241
|
+
if current.fingerprint() != baseline.fingerprint():
|
|
242
|
+
violations.append(RuntimeViolation(
|
|
243
|
+
test_name=test_name,
|
|
244
|
+
violation_type='execution_fingerprint_mismatch',
|
|
245
|
+
expected=baseline.fingerprint(),
|
|
246
|
+
actual=current.fingerprint(),
|
|
247
|
+
severity='critical',
|
|
248
|
+
description='Execution behavior fingerprint has changed'
|
|
249
|
+
))
|
|
250
|
+
|
|
251
|
+
# Performance regression check (warning only)
|
|
252
|
+
if current.execution_time_ms > baseline.execution_time_ms * 2:
|
|
253
|
+
violations.append(RuntimeViolation(
|
|
254
|
+
test_name=test_name,
|
|
255
|
+
violation_type='performance_regression',
|
|
256
|
+
expected=f"{baseline.execution_time_ms}ms",
|
|
257
|
+
actual=f"{current.execution_time_ms}ms",
|
|
258
|
+
severity='warning',
|
|
259
|
+
description='Execution time increased significantly'
|
|
260
|
+
))
|
|
261
|
+
|
|
262
|
+
return violations
|
|
263
|
+
|
|
264
|
+
def generate_report(self, violations: List[RuntimeViolation]) -> str:
|
|
265
|
+
"""Generate human-readable report of violations"""
|
|
266
|
+
if not violations:
|
|
267
|
+
return "✅ All runtime invariants validated successfully!\n"
|
|
268
|
+
|
|
269
|
+
report = []
|
|
270
|
+
report.append("=" * 70)
|
|
271
|
+
report.append("ZPICS RUNTIME VALIDATION REPORT")
|
|
272
|
+
report.append("=" * 70)
|
|
273
|
+
report.append("")
|
|
274
|
+
|
|
275
|
+
# Group by severity
|
|
276
|
+
critical = [v for v in violations if v.severity == 'critical']
|
|
277
|
+
warnings = [v for v in violations if v.severity == 'warning']
|
|
278
|
+
info = [v for v in violations if v.severity == 'info']
|
|
279
|
+
|
|
280
|
+
if critical:
|
|
281
|
+
report.append(f"❌ CRITICAL VIOLATIONS: {len(critical)}")
|
|
282
|
+
report.append("-" * 70)
|
|
283
|
+
for v in critical:
|
|
284
|
+
report.append(f" Test: {v.test_name}")
|
|
285
|
+
report.append(f" Type: {v.violation_type}")
|
|
286
|
+
report.append(f" {v.description}")
|
|
287
|
+
if v.violation_type in ['stdout_changed']:
|
|
288
|
+
report.append(f" Expected output:")
|
|
289
|
+
for line in str(v.expected).split('\n')[:5]:
|
|
290
|
+
report.append(f" {line}")
|
|
291
|
+
report.append(f" Actual output:")
|
|
292
|
+
for line in str(v.actual).split('\n')[:5]:
|
|
293
|
+
report.append(f" {line}")
|
|
294
|
+
else:
|
|
295
|
+
report.append(f" Expected: {v.expected}")
|
|
296
|
+
report.append(f" Actual: {v.actual}")
|
|
297
|
+
report.append("")
|
|
298
|
+
|
|
299
|
+
if warnings:
|
|
300
|
+
report.append(f"⚠️ WARNINGS: {len(warnings)}")
|
|
301
|
+
report.append("-" * 70)
|
|
302
|
+
for v in warnings:
|
|
303
|
+
report.append(f" Test: {v.test_name}")
|
|
304
|
+
report.append(f" {v.description}")
|
|
305
|
+
report.append("")
|
|
306
|
+
|
|
307
|
+
if info:
|
|
308
|
+
report.append(f"ℹ️ INFO: {len(info)}")
|
|
309
|
+
report.append("-" * 70)
|
|
310
|
+
for v in info:
|
|
311
|
+
report.append(f" Test: {v.test_name}")
|
|
312
|
+
report.append(f" {v.description}")
|
|
313
|
+
report.append("")
|
|
314
|
+
|
|
315
|
+
report.append("=" * 70)
|
|
316
|
+
report.append(f"Total violations: {len(violations)}")
|
|
317
|
+
report.append(f"Critical: {len(critical)} | Warnings: {len(warnings)} | Info: {len(info)}")
|
|
318
|
+
report.append("=" * 70)
|
|
319
|
+
|
|
320
|
+
return "\n".join(report)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def validate_runtime_changes(golden_tests_dir: str = "tests/golden") -> bool:
|
|
324
|
+
"""
|
|
325
|
+
Main entry point for validating runtime behavior changes
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
golden_tests_dir: Directory containing golden test files
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
True if all validations pass, False otherwise
|
|
332
|
+
"""
|
|
333
|
+
validator = ZPICSEvaluatorValidator()
|
|
334
|
+
all_violations = []
|
|
335
|
+
|
|
336
|
+
golden_dir = Path(golden_tests_dir)
|
|
337
|
+
if not golden_dir.exists():
|
|
338
|
+
print(f"⚠️ Golden tests directory not found: {golden_tests_dir}")
|
|
339
|
+
return True
|
|
340
|
+
|
|
341
|
+
# Process each golden test file
|
|
342
|
+
for test_file in golden_dir.glob("*.zx"):
|
|
343
|
+
test_name = test_file.stem
|
|
344
|
+
source_code = test_file.read_text()
|
|
345
|
+
|
|
346
|
+
# Create current snapshot
|
|
347
|
+
current = validator.create_snapshot(test_name, source_code)
|
|
348
|
+
|
|
349
|
+
# Load baseline
|
|
350
|
+
baseline = validator.load_snapshot(test_name)
|
|
351
|
+
|
|
352
|
+
if baseline is None:
|
|
353
|
+
# First time running - create baseline
|
|
354
|
+
print(f"📸 Creating runtime baseline for: {test_name}")
|
|
355
|
+
validator.save_snapshot(test_name, current)
|
|
356
|
+
continue
|
|
357
|
+
|
|
358
|
+
# Validate against baseline
|
|
359
|
+
violations = validator.validate_snapshot(test_name, current, baseline)
|
|
360
|
+
all_violations.extend(violations)
|
|
361
|
+
|
|
362
|
+
# Generate and print report
|
|
363
|
+
if all_violations:
|
|
364
|
+
print(validator.generate_report(all_violations))
|
|
365
|
+
return False
|
|
366
|
+
else:
|
|
367
|
+
print("✅ All runtime invariants validated successfully!")
|
|
368
|
+
print(f" Tested {len(list(golden_dir.glob('*.zx')))} golden test cases")
|
|
369
|
+
return True
|