feat: closes #2,#3,#4 — scripts pre_decimate + archive_job + check_jobs + tests
This commit is contained in:
54
tests/test_check_jobs.py
Normal file
54
tests/test_check_jobs.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _make_job_dir(base: Path, job_id: int, has_ply: bool = True, has_poses: bool = True) -> Path:
|
||||
job_dir = base / f"job_{job_id}"
|
||||
job_dir.mkdir(parents=True)
|
||||
if has_ply:
|
||||
(job_dir / "reconstruction.ply").write_bytes(b"\x00" * 100)
|
||||
if has_poses:
|
||||
(job_dir / "lingbot_poses.npz").touch()
|
||||
return job_dir
|
||||
|
||||
|
||||
def test_complete_job_is_ok():
|
||||
from scripts.check_jobs import check_job
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
_make_job_dir(Path(tmp), 1)
|
||||
result = check_job(1, tmp)
|
||||
assert result["status"] == "ok"
|
||||
assert result["job_id"] == 1
|
||||
assert result["missing"] == []
|
||||
|
||||
|
||||
def test_missing_ply_flagged():
|
||||
from scripts.check_jobs import check_job
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
_make_job_dir(Path(tmp), 2, has_ply=False)
|
||||
result = check_job(2, tmp)
|
||||
assert result["status"] == "incomplete"
|
||||
assert "reconstruction.ply" in result["missing"]
|
||||
|
||||
|
||||
def test_missing_poses_flagged():
|
||||
from scripts.check_jobs import check_job
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
_make_job_dir(Path(tmp), 3, has_poses=False)
|
||||
result = check_job(3, tmp)
|
||||
assert result["status"] == "incomplete"
|
||||
assert "lingbot_poses.npz" in result["missing"]
|
||||
|
||||
|
||||
def test_missing_job_dir_returns_missing():
|
||||
from scripts.check_jobs import check_job
|
||||
result = check_job(999, "/nonexistent/base")
|
||||
assert result["status"] == "missing"
|
||||
|
||||
|
||||
def test_decimated_flag_false_without_file():
|
||||
from scripts.check_jobs import check_job
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
_make_job_dir(Path(tmp), 4)
|
||||
result = check_job(4, tmp)
|
||||
assert result["details"]["decimated"] is False
|
||||
53
tests/test_pre_decimate.py
Normal file
53
tests/test_pre_decimate.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import numpy as np
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
|
||||
def _make_tiny_ply(path: Path) -> None:
|
||||
import open3d as o3d
|
||||
pcd = o3d.geometry.PointCloud()
|
||||
pts = np.random.rand(1000, 3).astype(np.float64)
|
||||
pcd.points = o3d.utility.Vector3dVector(pts)
|
||||
o3d.io.write_point_cloud(str(path), pcd)
|
||||
|
||||
|
||||
def test_decimate_reduces_points():
|
||||
from scripts.pre_decimate import decimate_ply
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
src = Path(tmp) / "model.ply"
|
||||
dst = Path(tmp) / "model_decimated.ply"
|
||||
_make_tiny_ply(src)
|
||||
decimate_ply(str(src), str(dst), max_pts=100)
|
||||
import open3d as o3d
|
||||
pcd = o3d.io.read_point_cloud(str(dst))
|
||||
# voxel downsampling is approximate — assert significantly fewer than original 1000
|
||||
assert len(pcd.points) < 500
|
||||
|
||||
|
||||
def test_decimate_small_cloud_unchanged():
|
||||
from scripts.pre_decimate import decimate_ply
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
src = Path(tmp) / "small.ply"
|
||||
dst = Path(tmp) / "small_decimated.ply"
|
||||
_make_tiny_ply(src)
|
||||
decimate_ply(str(src), str(dst), max_pts=5000)
|
||||
import open3d as o3d
|
||||
pcd = o3d.io.read_point_cloud(str(dst))
|
||||
assert len(pcd.points) == 1000
|
||||
|
||||
|
||||
def test_decimate_missing_src_raises():
|
||||
from scripts.pre_decimate import decimate_ply
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
with pytest.raises(FileNotFoundError):
|
||||
decimate_ply("/nonexistent.ply", str(Path(tmp) / "out.ply"))
|
||||
|
||||
|
||||
def test_find_ply_candidates():
|
||||
from scripts.pre_decimate import find_ply
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
d = Path(tmp)
|
||||
assert find_ply(d) is None
|
||||
(d / "model.ply").touch()
|
||||
assert find_ply(d) == d / "model.ply"
|
||||
Reference in New Issue
Block a user