Files
distribution/tests/domain_validate.sx
agra c3897e3508 P2.1: domain structs + boundary validation
Add the core distribution domain model under src/domain/ (App, Release,
Artifact, Channel, AuditEvent + Platform/Visibility/ValidationStatus/
RolloutPolicy enums) and a boundary validator that returns one distinct
typed ValidationErr per failure class (BadSlug, EmptyVersion, BadVersion,
BadChannelName, UnknownPlatform, MissingField, BadRollout).

Pure sx, depends only on modules/std.sx; lookups left as linear scans over
List (no HashMap). tests/domain_validate.sx asserts valid App/Release/
Artifact/Channel are accepted and each invalid case is rejected with the
exact expected error tag.
2026-06-05 23:02:41 +03:00

179 lines
5.8 KiB
Plaintext

// Acceptance for P2.1 — the domain boundary validator. Constructs valid
// App/Release/Artifact/Channel and asserts they are accepted, then mutates
// each into one invalid form and asserts it is rejected with the SPECIFIC
// typed ValidationErr (not merely "some failure"). Prints a pass/fail line
// per case and exits non-zero if any case behaves unexpectedly.
#import "modules/std.sx";
#import "../src/domain/platform.sx";
#import "../src/domain/app.sx";
#import "../src/domain/release.sx";
#import "../src/domain/artifact.sx";
#import "../src/domain/channel.sx";
#import "../src/domain/validate.sx";
// ── Valid fixtures ──────────────────────────────────────────────────────
valid_app :: () -> App {
a : App = .{
id = "app_01",
slug = "acme-app",
display_name = "Acme App",
owner = "user_01",
visibility = .public,
created_at = 1700000000,
updated_at = 1700000000,
};
a.bundle_ids.append(BundleId.{ platform = .ios, value = "co.acme.app" });
return a;
}
valid_release :: () -> Release {
return Release.{
id = "rel_01",
app_id = "app_01",
version = "1.2.3-beta.1",
build = 42,
channel = "stable",
notes = "first cut",
created_by = "user_01",
created_at = 1700000000,
updated_at = 1700000000,
};
}
valid_artifact :: () -> Artifact {
return Artifact.{
id = "art_01",
app_id = "app_01",
release_id = "rel_01",
platform = .android_apk,
filename = "acme.apk",
content_type = "application/vnd.android.package-archive",
size_bytes = 10485760,
sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
storage_key = "apps/app_01/rel_01/acme.apk",
validation_status = .valid,
};
}
valid_channel :: () -> Channel {
return Channel.{
app_id = "app_01",
name = "stable",
current_release_id = "rel_01",
policy = .percentage,
rollout_percent = 25,
};
}
// ── Cases ───────────────────────────────────────────────────────────────
check_accepts_app :: () -> bool {
a := valid_app();
ok := true;
validate_app(a) catch { ok = false; };
return ok;
}
check_accepts_release :: () -> bool {
r := valid_release();
ok := true;
validate_release(r) catch { ok = false; };
return ok;
}
check_accepts_artifact :: () -> bool {
a := valid_artifact();
ok := true;
validate_artifact(a) catch { ok = false; };
return ok;
}
check_accepts_channel :: () -> bool {
c := valid_channel();
ok := true;
validate_channel(c) catch { ok = false; };
return ok;
}
check_accepts_platform :: () -> bool {
p, e := parse_platform("android_apk");
ok := false;
if !e { ok = (p == .android_apk); }
return ok;
}
check_rejects_bad_slug :: () -> bool {
a := valid_app();
a.slug = "Bad_Slug"; // uppercase + underscore
matched := false;
validate_app(a) catch e { matched = (e == error.BadSlug); };
return matched;
}
check_rejects_empty_version :: () -> bool {
r := valid_release();
r.version = "";
matched := false;
validate_release(r) catch e { matched = (e == error.EmptyVersion); };
return matched;
}
check_rejects_bad_version :: () -> bool {
r := valid_release();
r.version = "1.2"; // missing PATCH component
matched := false;
validate_release(r) catch e { matched = (e == error.BadVersion); };
return matched;
}
check_rejects_unknown_platform :: () -> bool {
_, e := parse_platform("plan9");
return e == error.UnknownPlatform;
}
check_rejects_bad_channel :: () -> bool {
c := valid_channel();
c.name = "Bad Channel"; // space + uppercase
matched := false;
validate_channel(c) catch e { matched = (e == error.BadChannelName); };
return matched;
}
check_rejects_missing_field :: () -> bool {
a := valid_artifact();
a.sha256 = ""; // required field cleared
matched := false;
validate_artifact(a) catch e { matched = (e == error.MissingField); };
return matched;
}
run_case :: (label: string, ok: bool) -> s32 {
if ok { print(" PASS {}\n", label); return 0; }
print(" FAIL {}\n", label);
return 1;
}
main :: () -> s32 {
failures : s32 = 0;
failures += run_case("accept: valid app", check_accepts_app());
failures += run_case("accept: valid release", check_accepts_release());
failures += run_case("accept: valid artifact", check_accepts_artifact());
failures += run_case("accept: valid channel", check_accepts_channel());
failures += run_case("accept: platform 'android_apk'", check_accepts_platform());
failures += run_case("reject: bad slug -> BadSlug", check_rejects_bad_slug());
failures += run_case("reject: empty version -> EmptyVersion", check_rejects_empty_version());
failures += run_case("reject: bad version -> BadVersion", check_rejects_bad_version());
failures += run_case("reject: unknown platform -> UnknownPlatform", check_rejects_unknown_platform());
failures += run_case("reject: bad channel -> BadChannelName", check_rejects_bad_channel());
failures += run_case("reject: missing field -> MissingField", check_rejects_missing_field());
print("------------------------------------------------\n");
if failures == 0 {
print("domain_validate: ALL CASES PASS\n");
return 0;
}
print("domain_validate: {} CASE(S) FAILED\n", failures);
return 1;
}