From 6d828d0f461957b73ce83cd0a328d953c7a601a9 Mon Sep 17 00:00:00 2001 From: garasubo Date: Fri, 3 Apr 2026 17:39:14 +0900 Subject: [PATCH 1/4] add test runner --- .gitignore | 2 ++ scripts/gen-test-helper.sh | 21 +++++++++++++++++++++ scripts/run-tests.sh | 16 ++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 scripts/gen-test-helper.sh create mode 100755 scripts/run-tests.sh diff --git a/.gitignore b/.gitignore index 5b3bd554..300fc31a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ syntax: glob /target/ + +.test-helpers diff --git a/scripts/gen-test-helper.sh b/scripts/gen-test-helper.sh new file mode 100755 index 00000000..0957adea --- /dev/null +++ b/scripts/gen-test-helper.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -euxo pipefail + +UTILS=(cal dmesg hexdump lscpu lslocks lsmem) + +cd "$(dirname "$0")/../" +PROJECT_DIR="$(pwd)" +BINARY="$PROJECT_DIR/target/release/util-linux" + +mkdir -p .test-helpers + + +for util in "${UTILS[@]}"; do + cat > ".test-helpers/$util" < Date: Mon, 6 Apr 2026 16:05:28 +0900 Subject: [PATCH 2/4] add github action --- .github/workflows/run-gnu-test.yml | 52 ++++++++++++++++++++++++++++++ scripts/gen-test-helper.sh | 1 - scripts/run-tests.sh | 3 +- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/run-gnu-test.yml diff --git a/.github/workflows/run-gnu-test.yml b/.github/workflows/run-gnu-test.yml new file mode 100644 index 00000000..53410297 --- /dev/null +++ b/.github/workflows/run-gnu-test.yml @@ -0,0 +1,52 @@ + +name: Run GNU Test + +on: + pull_request: + push: + branches: + - 'main' + +jobs: + native: + name: Run GNU tests (native) + runs-on: ubuntu-24.04 + steps: + - name: Checkout code (uutils/util-linux) + uses: actions/checkout@v6 + with: + path: uutils-util-linux + - name: Checkout code (util-linux/util-linux) + uses: actions/checkout@v6 + with: + repository: util-linux/util-linux + path: gnu-util-linux + ref: v2.41.4 + - uses: Swatinem/rust-cache@v2 + with: + workspaces: "./uutils-util-linux -> target" + - name: Install dependencies + run: | + sudo apt-get update --quiet + sudo apt-get install -y \ + build-essential autoconf automake autopoint pkg-config \ + libtool gettext bison \ + bc socat ntp iproute2 squashfs-tools \ + libcap-ng-dev libpam-dev libudev-dev python3-dev libmount-dev libclang-dev libsmartcols-dev curl + - name: Build GNU tests + run: | + cd gnu-util-linux + ./autogen.sh + ./configure + make -j$(nproc) check-programs + - name: Run GNU tests + env: + GNU_PROJECT_DIR: ${{ github.workspace }}/gnu-util-linux + run: | + cd uutils-util-linux + ./scripts/run-tests.sh + + + + + diff --git a/scripts/gen-test-helper.sh b/scripts/gen-test-helper.sh index 0957adea..4eb91ad3 100755 --- a/scripts/gen-test-helper.sh +++ b/scripts/gen-test-helper.sh @@ -10,7 +10,6 @@ BINARY="$PROJECT_DIR/target/release/util-linux" mkdir -p .test-helpers - for util in "${UTILS[@]}"; do cat > ".test-helpers/$util" < Date: Sun, 26 Apr 2026 12:26:36 +0900 Subject: [PATCH 3/4] compare test results with baseline --- .github/workflows/run-gnu-test.yml | 22 ++++++- .gitignore | 1 + scripts/check-new-gnu-failures.sh | 96 ++++++++++++++++++++++++++++++ scripts/run-tests.sh | 11 ++++ 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100755 scripts/check-new-gnu-failures.sh diff --git a/.github/workflows/run-gnu-test.yml b/.github/workflows/run-gnu-test.yml index 53410297..41e6caf8 100644 --- a/.github/workflows/run-gnu-test.yml +++ b/.github/workflows/run-gnu-test.yml @@ -39,14 +39,30 @@ jobs: ./autogen.sh ./configure make -j$(nproc) check-programs + - name: Download test baseline if exists + id: download-test-baseline + continue-on-error: true + uses: actions/download-artifact@v8 + with: + name: gnu-test-failures + path: uutils-util-linux/.reference/ + - name: Run GNU tests env: GNU_PROJECT_DIR: ${{ github.workspace }}/gnu-util-linux run: | cd uutils-util-linux ./scripts/run-tests.sh - - - + - name: Update test baseline + if: github.ref == 'refs/heads/main' + run: | + cd uutils-util-linux + ./scripts/check-new-gnu-failures.sh --update-baseline + - name: Upload test baseline artifact + if: github.ref == 'refs/heads/main' || steps.download-test-baseline.outcome == 'failure' + uses: actions/upload-artifact@v7 + with: + name: gnu-test-failures + path: uutils-util-linux/.reference/gnu-test-failures.txt diff --git a/.gitignore b/.gitignore index 300fc31a..89305739 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ syntax: glob /target/ .test-helpers +.reference diff --git a/scripts/check-new-gnu-failures.sh b/scripts/check-new-gnu-failures.sh new file mode 100755 index 00000000..b19b8cbb --- /dev/null +++ b/scripts/check-new-gnu-failures.sh @@ -0,0 +1,96 @@ +#!/bin/bash +set -euo pipefail + +cd "$(dirname "$0")/../" +PROJECT_DIR="$(pwd)" +DIFF_DIR="$PROJECT_DIR/.test-helpers/tests/diff" +BASELINE="$PROJECT_DIR/.reference/gnu-test-failures.txt" +UPDATE_BASELINE=false +EMPTY_BASELINE=false + +for arg in "$@"; do + case "$arg" in + --update-baseline) UPDATE_BASELINE=true ;; + *) echo "Unknown argument: $arg" >&2; exit 2 ;; + esac +done + +# Collect current failures (exclude .err companion files) +current_tmp=$(mktemp) +trap 'rm -f "$current_tmp"' EXIT +if [[ -d "$DIFF_DIR" ]]; then + find "$DIFF_DIR" -mindepth 2 -maxdepth 2 -type f ! -name "*.err" -print0 \ + | sort -z \ + | while IFS= read -r -d '' path; do + echo "${path#"$DIFF_DIR/"}" + done > "$current_tmp" +fi + +# --update-baseline mode +if [[ "$UPDATE_BASELINE" == true ]]; then + { + echo "# Known GNU test failures - format: util/testname" + echo "# Update with: ./scripts/check-new-gnu-failures.sh --update-baseline" + cat "$current_tmp" + } > "$BASELINE" + count=$(wc -l < "$current_tmp") + echo "Baseline updated: $BASELINE ($count failures recorded)" + exit 0 +fi + +# Load baseline (strip comments and blank lines) +baseline_tmp=$(mktemp) +trap 'rm -f "$current_tmp" "$baseline_tmp"' EXIT +if [[ -f "$BASELINE" ]]; then + grep -v '^\s*#' "$BASELINE" | grep -v '^\s*$' | sort > "$baseline_tmp" +else + echo "WARNING: Baseline not found: $BASELINE" >&2 + echo " Run with --update-baseline to create it." >&2 + touch "$baseline_tmp" + EMPTY_BASELINE=true +fi + +# comm: -13 = lines only in current (new failures), -23 = lines only in baseline (fixed) +new_failures=$(comm -13 "$baseline_tmp" "$current_tmp") +fixed_tests=$(comm -23 "$baseline_tmp" "$current_tmp") + +# Report +echo "--- GNU test failure summary ---" +echo "Baseline failures: $(wc -l < "$baseline_tmp")" +echo "Current failures: $(wc -l < "$current_tmp")" +echo "" + +if [[ "$EMPTY_BASELINE" == true ]]; then + mkdir -p "$(dirname "$BASELINE")" + { + echo "# Known GNU test failures - format: util/testname" + echo "# Update with: ./scripts/check-new-gnu-failures.sh --update-baseline" + cat "$current_tmp" + } > "$BASELINE" + count=$(wc -l < "$current_tmp") + echo "Initial baseline created: $BASELINE ($count failures recorded)" + exit 0 +fi + +if [[ -n "$fixed_tests" ]]; then + echo "Tests newly FIXED:" + awk '{print " [FIXED] " $0}' <<< "$fixed_tests" + echo "" +fi + +if [[ -n "$new_failures" ]]; then + echo "Tests newly FAILING:" + awk '{print " [NEW FAILURE] " $0}' <<< "$new_failures" + echo "" + count=$(wc -l <<< "$new_failures") + echo "ERROR: $count new test failure(s) detected." >&2 + echo " Fix the regression, or if intentional, update the baseline:" >&2 + echo " ./scripts/check-new-gnu-failures.sh --update-baseline" >&2 + exit 1 +fi + +echo "No new failures. All current failures are known." +if [[ -n "$fixed_tests" ]]; then + echo "Consider updating the baseline to remove fixed tests:" + echo " ./scripts/check-new-gnu-failures.sh --update-baseline" +fi diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index ebc3f24a..773c28d8 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -9,7 +9,18 @@ cargo build --release ./scripts/gen-test-helper.sh +# Clear stale diff files from any previous run +rm -rf "$PROJECT_DIR/.test-helpers/tests/diff" + +# Run GNU tests; allow non-zero exit (known failures exist) +set +e "$GNU_PROJECT_DIR/tests/run.sh" \ --builddir="$PROJECT_DIR/.test-helpers" \ "$@" \ cal dmesg hexdump lscpu lslocks lsmem +GNU_TEST_EXIT=$? +set -e + +[[ $GNU_TEST_EXIT -ne 0 ]] && echo "GNU test runner exited with code $GNU_TEST_EXIT" + +./scripts/check-new-gnu-failures.sh From 89683f3005cf11e69d0ac3983330795113339268 Mon Sep 17 00:00:00 2001 From: garasubo Date: Fri, 1 May 2026 12:27:33 +0900 Subject: [PATCH 4/4] dynamic util list --- scripts/gen-test-helper.sh | 36 ++++++++++++++++++++++++++++++++++-- scripts/run-tests.sh | 9 ++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/scripts/gen-test-helper.sh b/scripts/gen-test-helper.sh index 4eb91ad3..dd98578e 100755 --- a/scripts/gen-test-helper.sh +++ b/scripts/gen-test-helper.sh @@ -2,14 +2,45 @@ set -euxo pipefail -UTILS=(cal dmesg hexdump lscpu lslocks lsmem) - cd "$(dirname "$0")/../" PROJECT_DIR="$(pwd)" BINARY="$PROJECT_DIR/target/release/util-linux" +if [[ -z "${GNU_PROJECT_DIR:-}" ]]; then + echo "ERROR: GNU_PROJECT_DIR is not set." >&2 + echo " Set it to the path of a gnu-util-linux checkout." >&2 + exit 2 +fi + +GNU_TS_DIR="$GNU_PROJECT_DIR/tests/ts" +if [[ ! -d "$GNU_TS_DIR" ]]; then + echo "ERROR: GNU test directory not found: $GNU_TS_DIR" >&2 + exit 2 +fi + mkdir -p .test-helpers +ours_tmp=$(mktemp) +gnu_tmp=$(mktemp) +trap 'rm -f "$ours_tmp" "$gnu_tmp"' EXIT + +for d in "$PROJECT_DIR/src/uu/"*/; do + basename "$d" +done | sort > "$ours_tmp" + +for d in "$GNU_TS_DIR/"*/; do + basename "$d" +done | sort > "$gnu_tmp" + +comm -12 "$ours_tmp" "$gnu_tmp" > "$PROJECT_DIR/.test-helpers/utils.list" + +mapfile -t UTILS < "$PROJECT_DIR/.test-helpers/utils.list" + +if [[ ${#UTILS[@]} -eq 0 ]]; then + echo "ERROR: No utilities matched between src/uu/ and $GNU_TS_DIR/" >&2 + exit 1 +fi + for util in "${UTILS[@]}"; do cat > ".test-helpers/$util" <&2 + exit 1 +fi + # Clear stale diff files from any previous run rm -rf "$PROJECT_DIR/.test-helpers/tests/diff" @@ -17,7 +24,7 @@ set +e "$GNU_PROJECT_DIR/tests/run.sh" \ --builddir="$PROJECT_DIR/.test-helpers" \ "$@" \ - cal dmesg hexdump lscpu lslocks lsmem + "${UTILS[@]}" GNU_TEST_EXIT=$? set -e