// Acceptance for P3.2 — the v0 publish manifest model + parse + validate. // // 1. Parses `examples/dist.json` into a typed `Manifest` and asserts the // fields (app/version/channel, the artifact count, and each artifact's // platform + path). // 2. Asserts each failure class surfaces a DISTINCT machine-readable error // (never a silent default): // - a missing required field (a manifest lacking `version`) -> MissingField // - an unknown platform ("psvita") -> UnknownPlatform // - a non-existent artifact path -> MissingArtifact // // Prints a PASS/FAIL line per case and exits non-zero if any case behaves // unexpectedly, so the test runner counts it as a failure. #import "modules/std.sx"; #import "../src/domain/platform.sx"; #import "../src/manifest/manifest.sx"; // ── happy path: examples/dist.json -> typed Manifest ──────────────────── check_parse_valid :: (alloc: Allocator) -> bool { m, e := load_manifest("examples/dist.json", alloc); if e { return false; } if m.app != "acme-app" { return false; } if m.version != "1.2.3" { return false; } if m.channel != "stable" { return false; } if m.artifacts.len != 2 { return false; } a0 := m.artifacts.items[0]; if a0.platform != .android_apk { return false; } if a0.path != "fixtures/acme-1.2.3-android.apk" { return false; } if a0.filename != "acme.apk" { return false; } if a0.content_type != "application/vnd.android.package-archive" { return false; } a1 := m.artifacts.items[1]; if a1.platform != .ios { return false; } if a1.path != "fixtures/acme-1.2.3-ios.ipa" { return false; } if a1.filename != "" { return false; } // optional override, absent -> "" return true; } // ── failure: a required field (version) is absent -> MissingField ─────── check_missing_version :: (alloc: Allocator) -> bool { src := "{\"app\":\"acme-app\",\"channel\":\"stable\",\"artifacts\":[{\"platform\":\"ios\",\"path\":\"fixtures/acme-1.2.3-ios.ipa\"}]}"; _, e := parse_manifest(src, alloc); return e == error.MissingField; } // ── failure: an artifact platform id is unknown -> UnknownPlatform ────── check_unknown_platform :: (alloc: Allocator) -> bool { src := "{\"app\":\"acme-app\",\"version\":\"1.2.3\",\"channel\":\"stable\",\"artifacts\":[{\"platform\":\"psvita\",\"path\":\"fixtures/acme-1.2.3-ios.ipa\"}]}"; _, e := parse_manifest(src, alloc); return e == error.UnknownPlatform; } // ── failure: an artifact path does not exist on disk -> MissingArtifact ─ // Parse SUCCEEDS (parse is filesystem-free); the missing file surfaces only // at validate time, against the manifest's base directory. check_missing_artifact_path :: (alloc: Allocator) -> bool { src := "{\"app\":\"acme-app\",\"version\":\"1.2.3\",\"channel\":\"stable\",\"artifacts\":[{\"platform\":\"ios\",\"path\":\"fixtures/does-not-exist.ipa\"}]}"; m, pe := parse_manifest(src, alloc); if pe { return false; } // parse must not fail here raised := false; matched := false; validate_manifest(m, "examples") catch err { raised = true; matched = (err == error.MissingArtifact); }; return raised and matched; } run_case :: (label: string, ok: bool) -> s32 { if ok { print(" PASS {}\n", label); return 0; } print(" FAIL {}\n", label); return 1; } main :: () -> s32 { gpa := GPA.init(); arena := Arena.init(xx gpa, 65536); defer arena.deinit(); failures : s32 = 0; failures += run_case("parse valid dist.json -> fields", check_parse_valid(xx arena)); failures += run_case("missing version -> MissingField", check_missing_version(xx arena)); failures += run_case("unknown platform 'psvita' -> UnknownPlatform", check_unknown_platform(xx arena)); failures += run_case("nonexistent path -> MissingArtifact", check_missing_artifact_path(xx arena)); print("------------------------------------------------\n"); if failures == 0 { print("manifest_parse: ALL CASES PASS\n"); return 0; } print("manifest_parse: {} CASE(S) FAILED\n", failures); return 1; }