Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/run-gnu-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

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: 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
syntax: glob

/target/

.test-helpers
.reference
96 changes: 96 additions & 0 deletions scripts/check-new-gnu-failures.sh
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions scripts/gen-test-helper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/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" <<EOF
#!/bin/bash
exec "$BINARY" $util "\$@"
EOF
chmod +x ".test-helpers/$util"
done

26 changes: 26 additions & 0 deletions scripts/run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

set -euxo pipefail

cd "$(dirname "$0")/../"
PROJECT_DIR="$(pwd)"

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make this list dynamic ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use:

UTILS=($(ls "$PROJECT_DIR/src/uu/"))
...
"${UTILS[@]}"

Same for gen-test-helper.sh.

Something fancier will be needed for setarch/i386/....

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Loading