feat: add Gaussian simulation workspace
This commit is contained in:
@@ -38,6 +38,8 @@ def test_gateway_uploads_lcc_bundle_with_tus_and_reads_provider_contract(tmp_pat
|
||||
"api_version": "gaussian-pipeline.api/v1",
|
||||
"upload_protocol": "tus/1.0.0",
|
||||
"source_transport": "tus-bundle/v1",
|
||||
"archive_transport": "tus-archive/v1",
|
||||
"archive_formats": ["zip", "rar", "7z"],
|
||||
"provider": {"id": "playcanvas-splat-transform", "version": "3.3.3"},
|
||||
"runtime": {
|
||||
"source_revision": "a" * 40,
|
||||
@@ -114,6 +116,92 @@ def test_gateway_uploads_lcc_bundle_with_tus_and_reads_provider_contract(tmp_pat
|
||||
assert descriptor.total_byte_length == sum(member.byte_length for member in descriptor.members)
|
||||
|
||||
|
||||
def test_gateway_uploads_and_normalizes_archive_with_tus(tmp_path: Path) -> None:
|
||||
archive_bytes = b"portable-archive"
|
||||
archive_sha = hashlib.sha256(archive_bytes).hexdigest()
|
||||
descriptor_bytes = b'{}'
|
||||
descriptor_sha = hashlib.sha256(descriptor_bytes).hexdigest()
|
||||
source_identity = {
|
||||
"format": "lcc2",
|
||||
"entrypoint": "result/scene.lcc2",
|
||||
"members": [{
|
||||
"logical_path": "result/scene.lcc2",
|
||||
"sha256": descriptor_sha,
|
||||
"byte_length": len(descriptor_bytes),
|
||||
}],
|
||||
}
|
||||
bundle_sha = hashlib.sha256(
|
||||
json.dumps(source_identity, ensure_ascii=False, separators=(",", ":")).encode()
|
||||
).hexdigest()
|
||||
received = bytearray()
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
if request.method == "GET" and request.url.path == "/v1/capabilities":
|
||||
return httpx.Response(200, json={
|
||||
"schema_version": "gaussian-pipeline.capabilities/v1",
|
||||
"service": "ndc-gaussian-pipeline",
|
||||
"api_version": "gaussian-pipeline.api/v1",
|
||||
"upload_protocol": "tus/1.0.0",
|
||||
"source_transport": "tus-bundle/v1",
|
||||
"archive_transport": "tus-archive/v1",
|
||||
"archive_formats": ["zip", "rar", "7z"],
|
||||
"runtime": {
|
||||
"source_revision": "a" * 40,
|
||||
"image_digest": f"sha256:{'b' * 64}",
|
||||
},
|
||||
"max_source_bytes": 1024,
|
||||
"max_source_files": 10_000,
|
||||
})
|
||||
if request.method == "POST" and request.url.path == "/v1/uploads":
|
||||
metadata = request.headers["upload-metadata"]
|
||||
assert "archive_name " in metadata
|
||||
assert "logical_path " not in metadata
|
||||
return httpx.Response(201, headers={"Location": "/v1/uploads/archive-001"})
|
||||
if request.method == "HEAD" and request.url.path.endswith("archive-001"):
|
||||
return httpx.Response(200, headers={"Upload-Offset": str(len(received))})
|
||||
if request.method == "PATCH" and request.url.path.endswith("archive-001"):
|
||||
received.extend(request.content)
|
||||
return httpx.Response(204, headers={"Upload-Offset": str(len(received))})
|
||||
if request.method == "POST" and request.url.path == "/v1/ingests":
|
||||
submitted = json.loads(request.content)
|
||||
assert submitted["archive"] == {
|
||||
"upload_id": "archive-001",
|
||||
"archive_name": "source.rar",
|
||||
"format": "rar",
|
||||
"sha256": archive_sha,
|
||||
"byte_length": len(archive_bytes),
|
||||
}
|
||||
return httpx.Response(201, json={
|
||||
"schema_version": "gaussian-pipeline.archive-ingest/v1",
|
||||
"ingest_id": "gsi-20260826000000-deadbeef",
|
||||
"source": {
|
||||
**source_identity,
|
||||
"bundle_sha256": bundle_sha,
|
||||
"total_byte_length": len(descriptor_bytes),
|
||||
"members": [{
|
||||
"upload_id": "ing-member-001",
|
||||
**source_identity["members"][0],
|
||||
}],
|
||||
},
|
||||
})
|
||||
return httpx.Response(404)
|
||||
|
||||
archive = tmp_path / "source.rar"
|
||||
archive.write_bytes(archive_bytes)
|
||||
with GaussianPipelineGateway(
|
||||
"http://gaussian.test",
|
||||
_token_file(tmp_path),
|
||||
chunk_bytes=5,
|
||||
transport=httpx.MockTransport(handler),
|
||||
) as gateway:
|
||||
uploaded = gateway.upload_source_archive(archive)
|
||||
source = gateway.normalize_archive(uploaded)
|
||||
|
||||
assert bytes(received) == archive_bytes
|
||||
assert source.entrypoint == "result/scene.lcc2"
|
||||
assert source.bundle_sha256 == bundle_sha
|
||||
|
||||
|
||||
def test_gateway_rejects_incomplete_lcc_bundle(tmp_path: Path) -> None:
|
||||
bundle = tmp_path / "bundle"
|
||||
bundle.mkdir()
|
||||
@@ -171,6 +259,8 @@ def test_gateway_rejects_upload_location_outside_provider(tmp_path: Path) -> Non
|
||||
"api_version": "gaussian-pipeline.api/v1",
|
||||
"upload_protocol": "tus/1.0.0",
|
||||
"source_transport": "tus-bundle/v1",
|
||||
"archive_transport": "tus-archive/v1",
|
||||
"archive_formats": ["zip", "rar", "7z"],
|
||||
"runtime": {
|
||||
"source_revision": "a" * 40,
|
||||
"image_digest": f"sha256:{'b' * 64}",
|
||||
@@ -295,6 +385,8 @@ def test_gateway_rejects_capabilities_without_runtime_provenance(tmp_path: Path)
|
||||
"api_version": "gaussian-pipeline.api/v1",
|
||||
"upload_protocol": "tus/1.0.0",
|
||||
"source_transport": "tus-bundle/v1",
|
||||
"archive_transport": "tus-archive/v1",
|
||||
"archive_formats": ["zip", "rar", "7z"],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user