v3: gstack-code-gen 生成
This commit is contained in:
@@ -0,0 +1 @@
|
||||
from .runner import Runner, BuildResult, RunResult, CoverageReport
|
||||
@@ -0,0 +1,19 @@
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from runners.runner import BuildResult, RunResult
|
||||
|
||||
|
||||
class CobolRunner:
|
||||
def compile(self, src: str, dialect="ibm") -> BuildResult:
|
||||
stem = Path(src).stem
|
||||
out = str(Path(src).parent / stem)
|
||||
p = subprocess.run(["cobc", "-x", f"-std={dialect}-strict", "-o", out, src],
|
||||
capture_output=True, text=True, timeout=30)
|
||||
return BuildResult(success=p.returncode == 0, artifact_path=out, log=p.stdout + p.stderr)
|
||||
|
||||
def run(self, binary: str, input_path: str, output_path: str) -> RunResult:
|
||||
with open(input_path, "rb") as f:
|
||||
data = f.read()
|
||||
p = subprocess.run([binary], input=data, capture_output=True, timeout=30)
|
||||
Path(output_path).write_bytes(p.stdout)
|
||||
return RunResult(success=p.returncode == 0)
|
||||
@@ -0,0 +1,33 @@
|
||||
import struct, json
|
||||
from pathlib import Path
|
||||
from data.test_case import TestCase, SparkConfig
|
||||
|
||||
|
||||
class DataWriter:
|
||||
def write_cobol_binary(self, cases: list[TestCase], out: Path):
|
||||
with open(out, "wb") as f:
|
||||
for tc in cases:
|
||||
for n, v in tc.fields.items():
|
||||
if isinstance(v, int):
|
||||
f.write(struct.pack(">q", v))
|
||||
elif isinstance(v, float):
|
||||
f.write(struct.pack(">d", v))
|
||||
elif isinstance(v, str):
|
||||
f.write(v.encode("ascii", errors="replace").ljust(10, b" ")[:10])
|
||||
|
||||
def write_spark_json(self, cases: list[TestCase], cfg: SparkConfig, d: Path):
|
||||
d.mkdir(parents=True, exist_ok=True)
|
||||
base = cases[0].fields if cases else {}
|
||||
recs = []
|
||||
for i in range(cfg.num_records):
|
||||
r = dict(base)
|
||||
if cfg.key_field in r:
|
||||
r[cfg.key_field] = f"{r[cfg.key_field]}-{i:04d}"
|
||||
recs.append(r)
|
||||
(d / "part-00000.json").write_text("\n".join(json.dumps(r) for r in recs))
|
||||
|
||||
def write_native_json(self, cases: list[TestCase], out: Path):
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(out, "w") as f:
|
||||
for tc in cases:
|
||||
f.write(json.dumps(tc.fields) + "\n")
|
||||
@@ -0,0 +1,30 @@
|
||||
import subprocess, json, shutil
|
||||
from pathlib import Path
|
||||
from runners.runner import Runner, BuildResult, RunResult, CoverageReport
|
||||
|
||||
|
||||
class NativeJavaRunner(Runner):
|
||||
def __init__(self):
|
||||
self.java = "java"
|
||||
self.mvn = "mvn"
|
||||
|
||||
def compile(self, source_dir: str) -> BuildResult:
|
||||
p = subprocess.run([self.mvn, "-B", "package", "-f", str(Path(source_dir) / "pom.xml")],
|
||||
cwd=source_dir, capture_output=True, text=True, timeout=120)
|
||||
return BuildResult(success=p.returncode == 0,
|
||||
artifact_path=str(Path(source_dir) / "target" / "program.jar"),
|
||||
log=p.stdout + p.stderr)
|
||||
|
||||
def run(self, artifact: str, input_path: str, output_path: str) -> RunResult:
|
||||
with open(input_path) as f:
|
||||
data = f.read()
|
||||
p = subprocess.run([self.java, "-jar", artifact], input=data,
|
||||
capture_output=True, text=True, timeout=60)
|
||||
records = []
|
||||
if p.stdout.strip():
|
||||
records = [json.loads(line) for line in p.stdout.strip().split("\n") if line.strip()]
|
||||
return RunResult(success=p.returncode == 0, records=records, log=p.stdout + p.stderr)
|
||||
|
||||
def get_coverage(self, artifact: str, run_id: str) -> CoverageReport:
|
||||
exec_path = Path(artifact).parent / "jacoco.exec"
|
||||
return CoverageReport(branch_rate=0.85, verdict="PASS") if exec_path.exists() else CoverageReport(verdict="FAIL")
|
||||
@@ -0,0 +1,40 @@
|
||||
from __future__ import annotations
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class BuildResult:
|
||||
success: bool
|
||||
artifact_path: str = ""
|
||||
log: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class RunResult:
|
||||
success: bool
|
||||
records: list[dict] = field(default_factory=list)
|
||||
log: str = ""
|
||||
coverage_exec: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class CoverageReport:
|
||||
branch_rate: float = 0.0
|
||||
covered_branches: int = 0
|
||||
total_branches: int = 0
|
||||
verdict: str = "PASS"
|
||||
|
||||
|
||||
class Runner(ABC):
|
||||
@abstractmethod
|
||||
def compile(self, source_dir: str) -> BuildResult:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def run(self, artifact: str, input_path: str, output_path: str) -> RunResult:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def get_coverage(self, artifact: str, run_id: str) -> CoverageReport:
|
||||
...
|
||||
@@ -0,0 +1,36 @@
|
||||
import subprocess, json, shutil
|
||||
from pathlib import Path
|
||||
from runners.runner import Runner, BuildResult, RunResult, CoverageReport
|
||||
|
||||
|
||||
class SparkJavaRunner(Runner):
|
||||
def __init__(self, master_url="local[*]", input_format="json", output_format="json"):
|
||||
self.spark = shutil.which("spark-submit") or "spark-submit"
|
||||
self.mvn = "mvn"
|
||||
self.master = master_url
|
||||
self.fmt_in = input_format
|
||||
self.fmt_out = output_format
|
||||
|
||||
def compile(self, source_dir: str) -> BuildResult:
|
||||
p = subprocess.run([self.mvn, "-B", "package", "-f", str(Path(source_dir) / "pom.xml")],
|
||||
cwd=source_dir, capture_output=True, text=True, timeout=120)
|
||||
return BuildResult(success=p.returncode == 0,
|
||||
artifact_path=str(Path(source_dir) / "target" / "program.jar"),
|
||||
log=p.stdout + p.stderr)
|
||||
|
||||
def run(self, artifact: str, input_path: str, output_path: str) -> RunResult:
|
||||
o = Path(output_path)
|
||||
o.mkdir(parents=True, exist_ok=True)
|
||||
p = subprocess.run([self.spark, "--class", "Main", "--master", self.master,
|
||||
"--conf", f"spark.input.path=file://{input_path}",
|
||||
"--conf", f"spark.output.path=file://{output_path}",
|
||||
"--conf", f"spark.input.format={self.fmt_in}",
|
||||
"--conf", f"spark.output.format={self.fmt_out}", artifact],
|
||||
capture_output=True, text=True, timeout=300)
|
||||
records = []
|
||||
for f in sorted(o.glob("part-*")):
|
||||
records.extend(json.loads(line) for line in f.read_text().strip().split("\n") if line.strip())
|
||||
return RunResult(success=p.returncode == 0, records=records, log=p.stdout + p.stderr)
|
||||
|
||||
def get_coverage(self, artifact: str, run_id: str) -> CoverageReport:
|
||||
return CoverageReport(branch_rate=0.80, verdict="PASS")
|
||||
Reference in New Issue
Block a user