diff options
| -rwxr-xr-x | bin/publish-apk | 17 | ||||
| -rwxr-xr-x | test/run-tests.sh | 16 |
2 files changed, 30 insertions, 3 deletions
diff --git a/bin/publish-apk b/bin/publish-apk index 91b4705..faf6db8 100755 --- a/bin/publish-apk +++ b/bin/publish-apk @@ -39,10 +39,21 @@ ACTUAL_HOST=$(hostname) || die "host is '$ACTUAL_HOST', expected '$EXPECT_HOST'. Build and test here, publish there." [ -f "$APK" ] || die "no such file: $APK" + # An .apk is a zip; an HTML error page or a truncated copy is not. -head -c 2 "$APK" | grep -q "PK" || die "$APK is not a zip archive — not a real APK" -unzip -l "$APK" 2>/dev/null | grep -q "AndroidManifest.xml" \ - || die "$APK has no AndroidManifest.xml — not an APK" +# +# Deliberately NOT `... | grep -q`: under `set -o pipefail` grep exits on its first match and +# SIGPIPEs the producer, so the pipeline reports failure on a file that is perfectly valid. +# This script hit exactly that on a real 112MB APK -- the trap is in this repo's own README, +# and it still caught me. Capture first, test second. +MAGIC=$(head -c 2 "$APK") +[ "$MAGIC" = "PK" ] || die "$APK is not a zip archive — not a real APK" + +LISTING=$(unzip -l "$APK" 2>/dev/null) +case "$LISTING" in + *AndroidManifest.xml*) ;; + *) die "$APK has no AndroidManifest.xml — not an APK" ;; +esac [ -d "$DEST_DIR" ] || die "no such directory: $DEST_DIR" DEST="$DEST_DIR/$NAME" diff --git a/test/run-tests.sh b/test/run-tests.sh index a88e024..415ecc3 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -276,5 +276,21 @@ else bad "apk validation" "rc=$rc out=$out" fi +# 23. A real, large APK must be accepted. The first version of the zip check used +# `unzip -l | grep -q`, which under pipefail SIGPIPEs unzip and rejects valid files -- +# the very trap this repo's README documents. +realapk="$tmproot/real.apk" +mkdir -p "$tmproot/apkbuild/res" +printf 'manifest' > "$tmproot/apkbuild/AndroidManifest.xml" +# Enough entries that grep matches well before the listing ends, which is when SIGPIPE bites. +for i in $(seq 1 300); do printf 'x%.0s' $(seq 1 100) > "$tmproot/apkbuild/res/f$i.bin"; done +( cd "$tmproot/apkbuild" && zip -q -r "$realapk" . ) +out=$("$BIN/publish-apk" "$realapk" thing.apk --host "$(hostname)" --dir "$tmproot/nonexistent" 2>&1); rc=$? +if printf '%s' "$out" | grep -qi "not an APK\|not a zip"; then + bad "valid APK rejected" "out=$out" +else + ok "accepts a real multi-entry APK (no SIGPIPE from the zip check)" +fi + printf '\n=== summary: %d passed, %d failed ===\n' "$pass" "$fail" [ "$fail" -eq 0 ] |
