#!/usr/bin/env bash # Which packages of the workspace are tested where: see tools/README.md and docs/dev/build-and-test.md. # # tools/test-partition check fail when the classification and the workspace disagree # tools/test-partition packages print `-p a -p b` for cargo # tools/test-partition expr print a nextest filterset: `package(a) | package(b)` # tools/test-partition expr recorder-macos # the filterset of the recorder tests that run on macOS # tools/test-partition --self-test run `check` against the tree and against deliberately broken copies # # The classification is tools/test-partition.json (class -> package names); it is the single source of truth # for the CI jobs, the justfile and the Nix check sets (nix/windows). It needs only bash, cargo and jq. # # Environment (for the self-test): TEST_PARTITION_JSON overrides the classification file, and # TEST_PARTITION_METADATA is a file with the output of `cargo metadata --format-version 1 --no-deps`. set -euo pipefail root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) json=${TEST_PARTITION_JSON:-$root/tools/test-partition.json} classes="neutral os_sensitive windows linux macos mixed tool none" # the crates a `neutral` package must not depend on, directly platform_crates='["komorebi-windows","komorebi-macos","komorebi-linux"]' # the tests of the recorder that run on macOS, by their module path: the macOS flavoured sources, which # the recorder's other tests (the platform-neutral ones) share a binary with recorder_macos_filter='package(komorebi-recorder) & test(/^(sources::oslog|av|capture::sck|platform|power|system_state)::/)' die() { echo "test-partition: $*" >&2 exit 1 } metadata() { if [ -n "${TEST_PARTITION_METADATA:-}" ]; then cat "$TEST_PARTITION_METADATA" else (cd "$root" && cargo metadata --format-version 1 --no-deps) fi } valid_class() { case " $classes " in *" $1 "*) return 0 ;; *) return 1 ;; esac } check() { local meta problems meta=$(metadata) problems=$( jq -r --argjson platform "$platform_crates" --slurpfile part "$json" --arg classes "$classes" ' ($part[0]) as $p | [ .packages[] ] as $pkgs | ($classes | split(" ")) as $known | ( # classes the file has that are not part of the contract ($p | keys[] | select(. as $k | $known | index($k) | not) | "unknown class \(.)"), # a member in no class, or in two ($pkgs[].name as $n | [ $known[] as $c | select(($p[$c] // []) | index($n)) | $c ] as $in | if ($in | length) == 0 then "\($n): in no class" elif ($in | length) > 1 then "\($n): in two classes (\($in | join(", ")))" else empty end), # a name that is no member (stale), or listed twice in one class ($known[] as $c | ($p[$c] // [])[] as $n | select(($pkgs | map(.name) | index($n)) == null) | "\($n) (\($c)): not a member of the workspace"), ($known[] as $c | ($p[$c] // []) | group_by(.)[] | select(length > 1) | "\(.[0]): listed twice in \($c)"), # a neutral package that is not neutral ($pkgs[] | select(.name as $n | ($p.neutral // []) | index($n)) | .name as $n | (.dependencies[] | select(.target != null) | "\($n): neutral, but depends on \(.name) only for \(.target)"), (.dependencies[] | select(.name as $d | $platform | index($d)) | "\($n): neutral, but depends on the platform crate \(.name)") ) ) ' <<<"$meta" ) if [ -n "$problems" ]; then echo "$problems" >&2 echo "test-partition: tools/test-partition.json does not match the workspace" >&2 return 1 fi } members_of() { jq -r --arg c "$1" '.[$c] // [] | .[]' "$json" } cmd=${1:-} case "$cmd" in check) check ;; packages) class=${2:-} valid_class "$class" || die "unknown class '$class' (one of: $classes)" members_of "$class" | sed 's/^/-p /' | paste -sd' ' - ;; expr) class=${2:-} if [ "$class" = recorder-macos ]; then echo "$recorder_macos_filter" exit 0 fi valid_class "$class" || die "unknown class '$class' (one of: $classes)" members_of "$class" | sed 's/.*/package(&)/' | paste -sd'|' - | sed 's/|/ | /g' ;; --self-test) exec "$root/tools/test-partition.test" "$root/tools/test-partition" ;; *) sed -n '2,9p' "$0" | sed 's/^# \{0,1\}//' >&2 exit 2 ;; esac