[PR #4046] test(android): build split-set fixtures with aapt2 and read them with the manifest reader #6018

Open
opened 2026-10-31 01:11:12 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4046
Author: @cevieiras
Created: 10/15/2026
Status: 🔄 Open

Base: main ← Head: test/android-split-set-fixtures


📝 Commits (6)

  • 24bfc62 feat(android): check split APK set consistency from manifest facts
  • ecc9755 feat(artifacts): read compiled AndroidManifest.xml attributes
  • c7e35ef fix(android): keep unknown split-set facts unknown and order reasons
  • 2e55539 fix(artifacts): keep AXML decoding strict and bounded
  • 865355f test(android): build split-set fixtures with a caller-supplied aapt2
  • 7010ec4 test(android): cover the manifest reader with aapt2-built manifests

📊 Changes

22 files changed (+2059 additions, -0 deletions)

View changed files

📝 knip.json (+1 -0)
➕ scripts/fixtures/android/split-set.mjs (+100 -0)
➕ scripts/fixtures/android/split-set/base-version-major.xml (+5 -0)
➕ scripts/fixtures/android/split-set/base-version-mismatch.xml (+5 -0)
➕ scripts/fixtures/android/split-set/base.xml (+5 -0)
➕ scripts/fixtures/android/split-set/config-arm64_v8a.xml (+4 -0)
➕ scripts/fixtures/android/split-set/config-en.xml (+4 -0)
➕ scripts/fixtures/android/split-set/config-feature_x-xxhdpi.xml (+4 -0)
➕ scripts/fixtures/android/split-set/config-orphan.xml (+4 -0)
➕ scripts/fixtures/android/split-set/config-xxhdpi.xml (+4 -0)
➕ scripts/fixtures/android/split-set/feature_x.xml (+4 -0)
➕ src/artifacts/android/AndroidManifestReader.producer.test.ts (+78 -0)
➕ src/artifacts/android/AndroidManifestReader.test.ts (+376 -0)
➕ src/artifacts/android/AndroidManifestReader.ts (+463 -0)
➕ src/artifacts/android/AndroidSplitSetApks.fixture.ts (+22 -0)
➕ src/artifacts/android/AxmlBytes.ts (+40 -0)
➕ src/artifacts/android/AxmlStringPool.ts (+143 -0)
➕ src/artifacts/android/androidSplitSetFixtures.ts (+26 -0)
➕ src/artifacts/android/axmlBuilder.fixture.ts (+149 -0)
➕ src/domain/android/androidManifestFacts.ts (+39 -0)

...and 2 more files

📄 Description

Stacked on #3495 and #3496. This branch carries their commits; please review only the last two commits (test(android): build split-set fixtures ... and test(android): cover the manifest reader ...). I will rebase as those land. Opened as a draft until then.

Summary

Adds synthetic split-set fixtures compiled from tracked manifest sources with a caller-supplied aapt2, and tests that read their producer-built manifests with the reader from #3496. It gives the reader and the set check from #3495 evidence from a real producer instead of only hand-built bytes. No tool surface.

Refs #1813

Problem and expected behavior

The reader's tests so far use hand-built binary XML, which can only encode what its author already assumed. A real aapt2 link output exercises resource ids, attribute ordering and string-pool layout as a real producer emits them.

Change and scope

  • scripts/fixtures/android/split-set.mjs plus the manifest sources under scripts/fixtures/android/split-set/: build base, ABI/language/density config splits, a feature split and its config split, and version-mismatch and orphan variants. aapt2, android.jar and zip are caller-supplied; nothing is downloaded or installed.
  • AndroidSplitSetApks.fixture.ts: the generated whole-APK bytes (base64), so CI needs no aapt2. Regenerate with --emit-golden.
  • androidSplitSetFixtures.ts and AndroidManifestReader.producer.test.ts: load a fixture and assert the facts the reader returns.
  • knip.json: registers the generator script as an entry.
  • Not included: the APK/ZIP adapter, any tool surface.

Contract and boundary impact

  • Semantic owner and earliest changed stage: test fixtures and a developer script; no runtime code.
  • CLI and MCP/tool-catalog contract: none.
  • Provider, bridge, target-format, or platform compatibility: aapt2 is used only by the generator, not at test time.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Process execution, authorization, cleanup, or containment impact: the generator runs the caller-supplied aapt2 and zip, only when run by hand.
  • Generated metadata, package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated: AndroidManifestReader.producer.test.ts (7 tests) over aapt2-built manifests.

  • Base reproduction or other evidence: the golden bytes were produced by running the generator once; the facts are asserted exactly, including SDK range, sandbox version, isSplitRequired on <application> and configForSplit.

  • User-visible CLI/MCP output: none.

  • Remaining proof gaps: the generated header does not record the aapt2 version; manifests from large real applications are still not covered by committed fixtures.

  • Observed, derived, and inferred claims remain distinguishable.

  • Artifact identity, source provenance, and failed attempts remain preserved.

  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

On this branch tip, rebased on the reader branch:

  • npm run test:focused -- src/artifacts/android/AndroidManifestReader.test.ts src/artifacts/android/AndroidManifestReader.producer.test.ts src/domain/android/androidSplitSet.test.ts — 52 passed
  • npm run check — 6/6 tasks successful
  • npm run verify:architecture-guards — passed

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: fixtures are synthetic and contain no third-party application content.

Author readiness

Human owner:

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4046 **Author:** [@cevieiras](https://github.com/cevieiras) **Created:** 10/15/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `test/android-split-set-fixtures` --- ### 📝 Commits (6) - [`24bfc62`](https://github.com/morluto/rea/commit/24bfc6203ec80c481e6ef67010d6e5221bc49e1c) feat(android): check split APK set consistency from manifest facts - [`ecc9755`](https://github.com/morluto/rea/commit/ecc975570379985cb59a58dc1fd1152aeccdf937) feat(artifacts): read compiled AndroidManifest.xml attributes - [`c7e35ef`](https://github.com/morluto/rea/commit/c7e35ef23185d2b0490aa91ec20e9142ccfcf509) fix(android): keep unknown split-set facts unknown and order reasons - [`2e55539`](https://github.com/morluto/rea/commit/2e5553907406566983d211e3e1c754f66fbebab4) fix(artifacts): keep AXML decoding strict and bounded - [`865355f`](https://github.com/morluto/rea/commit/865355f0ea5d556b74ddd5f635c70ad78ca0c749) test(android): build split-set fixtures with a caller-supplied aapt2 - [`7010ec4`](https://github.com/morluto/rea/commit/7010ec46dccfa617ee573aa74699b1a17001f4c9) test(android): cover the manifest reader with aapt2-built manifests ### 📊 Changes **22 files changed** (+2059 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `knip.json` (+1 -0) ➕ `scripts/fixtures/android/split-set.mjs` (+100 -0) ➕ `scripts/fixtures/android/split-set/base-version-major.xml` (+5 -0) ➕ `scripts/fixtures/android/split-set/base-version-mismatch.xml` (+5 -0) ➕ `scripts/fixtures/android/split-set/base.xml` (+5 -0) ➕ `scripts/fixtures/android/split-set/config-arm64_v8a.xml` (+4 -0) ➕ `scripts/fixtures/android/split-set/config-en.xml` (+4 -0) ➕ `scripts/fixtures/android/split-set/config-feature_x-xxhdpi.xml` (+4 -0) ➕ `scripts/fixtures/android/split-set/config-orphan.xml` (+4 -0) ➕ `scripts/fixtures/android/split-set/config-xxhdpi.xml` (+4 -0) ➕ `scripts/fixtures/android/split-set/feature_x.xml` (+4 -0) ➕ `src/artifacts/android/AndroidManifestReader.producer.test.ts` (+78 -0) ➕ `src/artifacts/android/AndroidManifestReader.test.ts` (+376 -0) ➕ `src/artifacts/android/AndroidManifestReader.ts` (+463 -0) ➕ `src/artifacts/android/AndroidSplitSetApks.fixture.ts` (+22 -0) ➕ `src/artifacts/android/AxmlBytes.ts` (+40 -0) ➕ `src/artifacts/android/AxmlStringPool.ts` (+143 -0) ➕ `src/artifacts/android/androidSplitSetFixtures.ts` (+26 -0) ➕ `src/artifacts/android/axmlBuilder.fixture.ts` (+149 -0) ➕ `src/domain/android/androidManifestFacts.ts` (+39 -0) _...and 2 more files_ </details> ### 📄 Description > **Stacked on #3495 and #3496.** This branch carries their commits; please review only the last two commits (`test(android): build split-set fixtures ...` and `test(android): cover the manifest reader ...`). I will rebase as those land. Opened as a draft until then. ## Summary Adds synthetic split-set fixtures compiled from tracked manifest sources with a caller-supplied `aapt2`, and tests that read their producer-built manifests with the reader from #3496. It gives the reader and the set check from #3495 evidence from a real producer instead of only hand-built bytes. No tool surface. Refs #1813 ## Problem and expected behavior The reader's tests so far use hand-built binary XML, which can only encode what its author already assumed. A real `aapt2 link` output exercises resource ids, attribute ordering and string-pool layout as a real producer emits them. ## Change and scope - `scripts/fixtures/android/split-set.mjs` plus the manifest sources under `scripts/fixtures/android/split-set/`: build base, ABI/language/density config splits, a feature split and its config split, and version-mismatch and orphan variants. `aapt2`, `android.jar` and `zip` are caller-supplied; nothing is downloaded or installed. - `AndroidSplitSetApks.fixture.ts`: the generated whole-APK bytes (base64), so CI needs no `aapt2`. Regenerate with `--emit-golden`. - `androidSplitSetFixtures.ts` and `AndroidManifestReader.producer.test.ts`: load a fixture and assert the facts the reader returns. - `knip.json`: registers the generator script as an entry. - Not included: the APK/ZIP adapter, any tool surface. ## Contract and boundary impact - Semantic owner and earliest changed stage: test fixtures and a developer script; no runtime code. - CLI and MCP/tool-catalog contract: none. - Provider, bridge, target-format, or platform compatibility: `aapt2` is used only by the generator, not at test time. - Evidence, artifact, provenance, or reconstruction contract: none. - Process execution, authorization, cleanup, or containment impact: the generator runs the caller-supplied `aapt2` and `zip`, only when run by hand. - Generated metadata, package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated: `AndroidManifestReader.producer.test.ts` (7 tests) over aapt2-built manifests. - Base reproduction or other evidence: the golden bytes were produced by running the generator once; the facts are asserted exactly, including SDK range, sandbox version, `isSplitRequired` on `<application>` and `configForSplit`. - User-visible CLI/MCP output: none. - Remaining proof gaps: the generated header does not record the `aapt2` version; manifests from large real applications are still not covered by committed fixtures. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed On this branch tip, rebased on the reader branch: - `npm run test:focused -- src/artifacts/android/AndroidManifestReader.test.ts src/artifacts/android/AndroidManifestReader.producer.test.ts src/domain/android/androidSplitSet.test.ts` — 52 passed - `npm run check` — 6/6 tasks successful - `npm run verify:architecture-guards` — passed ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. - Package or release metadata impact: none. - Security, privacy, process, or containment review: fixtures are synthetic and contain no third-party application content. ## Author readiness <!-- The human owner completes these declarations before requesting review. The PR author is the owner by default. A different owner must explicitly accept ownership on this PR. AI agents must leave these declarations to a human to dictate to them or there could be catastrophic consequences for many users of REA. Draft PRs may leave them unchecked. These declarations record initial readiness when opening the PR for review; later pushes do not require a new human sign-off. Keep the description and validation evidence current as the work changes. See CONTRIBUTING.md#pull-request-ownership-and-readiness. --> Human owner: <!-- @GitHub-handle --> - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge <!-- Draft PRs may leave pending items unchecked. Resolve material scope and authority questions before integration. --> - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6018
No description provided.