diff --git a/test-projects/README.md b/test-projects/README.md index 3a378e1..0e88cc3 100644 --- a/test-projects/README.md +++ b/test-projects/README.md @@ -28,10 +28,12 @@ anything the scan does not reach. ## The `app/` directory each one builds into -`find_apks` matches APKs up to **two** directories below a project root, and -it is run against the *project* path, not a component's `cwd`. A test -project building into `test-projects//build/outputs/apk/` would -therefore also be found from the repository root -- offered as a build of +`find_apks` matches APKs up to **two** directories below where it is +anchored, and it is anchored at a component's own directory -- +`project.join(cwd)`, which is the project path itself for a component +declaring no `cwd`, as all of these do except `two-clients`. A test project +building into `test-projects//build/outputs/apk/` would therefore also +be found from the repository root -- offered as a build of Dev Updater itself, and, being the newest, served as the default. Somebody pressing Update on the Dev Updater card would get a stub app. @@ -57,8 +59,9 @@ appear. | `two-variants` | Builds `debug` and `release`, so the phone gets a variant picker and `resolve_apk` has something to fall back from. | | `breakable` | `touch breakable/break-the-build` and its next build fails, in colour, on stderr. `rm` it and it stops. | | `service-and-app` | A `Server` beside an `Apk`: two components building at once, the whole service contract, a runtime log that is not this server's own, and a `resources:` declaration giving Uninstall real paths. | +| `two-clients` | Two `Apk` components in one checkout, each with its own `cwd` and package. The only fixture where *two* components produce an APK, which is what per-component discovery, the per-component "never built at all" check, and `?component=` all need to be exercised against. `tablet` is slow on purpose so that building one rather than both is visible. | -All four are unaccepted when first added, so each is also a run through the +All five are unaccepted when first added, so each is also a run through the acceptance gate. ## The apps themselves diff --git a/test-projects/two-clients/.dev-updater.ron b/test-projects/two-clients/.dev-updater.ron new file mode 100644 index 0000000..5d27ca9 --- /dev/null +++ b/test-projects/two-clients/.dev-updater.ron @@ -0,0 +1,45 @@ +// A test project for Dev Updater, not a real app. See ../README.md. +// +// Two independent Android clients in one checkout, each with its own `cwd` +// and its own package. That is the shape tdep-survey has, and the one no +// other fixture here covers: `service-and-app` also has two components, but +// only one of them produces an APK, so everything that goes wrong when +// *two* do is invisible to it. +// +// Three things it exists to keep honest, all of which were real bugs: +// +// - Each component's builds are found under its own directory. +// `APK_PATTERNS` is anchored at `project.join(cwd)`; anchored at the +// project root instead, its two-level pattern reaches both clients' +// outputs and whichever matched first was reported as *every* +// component's package, size, variants and mtime. Two clients installing +// over different packages is what makes that wrong rather than merely +// redundant -- the card would check one app's installed state and +// report it as the other's. +// +// - "Never built at all" is asked per component. Because the +// root-anchored scan sees both, building either client once made the +// whole project read as "something is built here", and the other one -- +// never built -- silently stopped being offered its own first build. +// +// - Building one component instead of every one. `tablet` is slow on +// purpose so that `?component=` is *visible*: pressing Update on +// `phone` finishes in about two seconds, and paying for the tablet's +// build to get it is the whole complaint that scoping exists to answer. +label: "Test: Two Clients", + +components: [ + Apk( + name: "phone", + // The command resolves against the project root while `cwd` says + // where to run it, so this is not `./build.sh` -- same split as + // Dev Updater's own declaration. + build: "phone/build.sh", + cwd: "phone", + ), + Apk( + name: "tablet", + build: "tablet/build.sh", + cwd: "tablet", + ), +], diff --git a/test-projects/two-clients/phone/build.sh b/test-projects/two-clients/phone/build.sh new file mode 100755 index 0000000..e530cad --- /dev/null +++ b/test-projects/two-clients/phone/build.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# Builds this project's phone client -- the fast half of the pair, so that +# the two components finishing at visibly different times is the fixture's +# own evidence that only one of them ran. +# +# Run from `two-clients/phone`, which is this component's `cwd`, so the +# shared builder writes into `phone/app/build/outputs/apk/` and the APK is +# reachable from this component's directory but not from the project root's +# two-level patterns. +set -eu +../../lib/build-apk.sh --package com.example.dutest.phone --label "Test Phone" diff --git a/test-projects/two-clients/tablet/build.sh b/test-projects/two-clients/tablet/build.sh new file mode 100755 index 0000000..452ed56 --- /dev/null +++ b/test-projects/two-clients/tablet/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# Builds this project's tablet client -- the slow half of the pair, on +# purpose. A real second client is slow for a real reason (an ARM +# cross-compile, an NDK step); here it is six seconds of pretending, which +# is enough to see that pressing Update on `phone` did not wait for it. +# +# Reports its own progress, so the sleep also exercises a per-component bar +# next to a component that finishes before the bar has moved. +set -eu + +STEPS=6 +i=0 +while [ "$i" -lt "$STEPS" ]; do + i=$((i + 1)) + echo "@@progress $i/$STEPS" + echo "==> Cross-compiling native bits, part $i of $STEPS" + sleep 1 +done + +../../lib/build-apk.sh --package com.example.dutest.tablet --label "Test Tablet"