Skip to content

Commit a2e41f9

Browse files
authored
Merge pull request #517 from garasubo/feat/add-gnu-tests
feat: run GNU testsuite
1 parent 588e410 commit a2e41f9

5 files changed

Lines changed: 252 additions & 0 deletions

File tree

.github/workflows/run-gnu-test.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
name: Run GNU Test
3+
4+
on:
5+
pull_request:
6+
push:
7+
branches:
8+
- 'main'
9+
10+
jobs:
11+
native:
12+
name: Run GNU tests (native)
13+
runs-on: ubuntu-24.04
14+
steps:
15+
- name: Checkout code (uutils/util-linux)
16+
uses: actions/checkout@v6
17+
with:
18+
path: uutils-util-linux
19+
- name: Checkout code (util-linux/util-linux)
20+
uses: actions/checkout@v6
21+
with:
22+
repository: util-linux/util-linux
23+
path: gnu-util-linux
24+
ref: v2.41.4
25+
- uses: Swatinem/rust-cache@v2
26+
with:
27+
workspaces: "./uutils-util-linux -> target"
28+
- name: Install dependencies
29+
run: |
30+
sudo apt-get update --quiet
31+
sudo apt-get install -y \
32+
build-essential autoconf automake autopoint pkg-config \
33+
libtool gettext bison \
34+
bc socat ntp iproute2 squashfs-tools \
35+
libcap-ng-dev libpam-dev libudev-dev python3-dev libmount-dev libclang-dev libsmartcols-dev curl
36+
- name: Build GNU tests
37+
run: |
38+
cd gnu-util-linux
39+
./autogen.sh
40+
./configure
41+
make -j$(nproc) check-programs
42+
- name: Download test baseline if exists
43+
id: download-test-baseline
44+
continue-on-error: true
45+
uses: actions/download-artifact@v8
46+
with:
47+
name: gnu-test-failures
48+
path: uutils-util-linux/.reference/
49+
50+
- name: Run GNU tests
51+
env:
52+
GNU_PROJECT_DIR: ${{ github.workspace }}/gnu-util-linux
53+
run: |
54+
cd uutils-util-linux
55+
./scripts/run-tests.sh
56+
57+
- name: Update test baseline
58+
if: github.ref == 'refs/heads/main'
59+
run: |
60+
cd uutils-util-linux
61+
./scripts/check-new-gnu-failures.sh --update-baseline
62+
63+
- name: Upload test baseline artifact
64+
if: github.ref == 'refs/heads/main' || steps.download-test-baseline.outcome == 'failure'
65+
uses: actions/upload-artifact@v7
66+
with:
67+
name: gnu-test-failures
68+
path: uutils-util-linux/.reference/gnu-test-failures.txt

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
syntax: glob
22

33
/target/
4+
5+
.test-helpers
6+
.reference

scripts/check-new-gnu-failures.sh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
cd "$(dirname "$0")/../"
5+
PROJECT_DIR="$(pwd)"
6+
DIFF_DIR="$PROJECT_DIR/.test-helpers/tests/diff"
7+
BASELINE="$PROJECT_DIR/.reference/gnu-test-failures.txt"
8+
UPDATE_BASELINE=false
9+
EMPTY_BASELINE=false
10+
11+
for arg in "$@"; do
12+
case "$arg" in
13+
--update-baseline) UPDATE_BASELINE=true ;;
14+
*) echo "Unknown argument: $arg" >&2; exit 2 ;;
15+
esac
16+
done
17+
18+
# Collect current failures (exclude .err companion files)
19+
current_tmp=$(mktemp)
20+
trap 'rm -f "$current_tmp"' EXIT
21+
if [[ -d "$DIFF_DIR" ]]; then
22+
find "$DIFF_DIR" -mindepth 2 -maxdepth 2 -type f ! -name "*.err" -print0 \
23+
| sort -z \
24+
| while IFS= read -r -d '' path; do
25+
echo "${path#"$DIFF_DIR/"}"
26+
done > "$current_tmp"
27+
fi
28+
29+
# --update-baseline mode
30+
if [[ "$UPDATE_BASELINE" == true ]]; then
31+
{
32+
echo "# Known GNU test failures - format: util/testname"
33+
echo "# Update with: ./scripts/check-new-gnu-failures.sh --update-baseline"
34+
cat "$current_tmp"
35+
} > "$BASELINE"
36+
count=$(wc -l < "$current_tmp")
37+
echo "Baseline updated: $BASELINE ($count failures recorded)"
38+
exit 0
39+
fi
40+
41+
# Load baseline (strip comments and blank lines)
42+
baseline_tmp=$(mktemp)
43+
trap 'rm -f "$current_tmp" "$baseline_tmp"' EXIT
44+
if [[ -f "$BASELINE" ]]; then
45+
grep -v '^\s*#' "$BASELINE" | grep -v '^\s*$' | sort > "$baseline_tmp"
46+
else
47+
echo "WARNING: Baseline not found: $BASELINE" >&2
48+
echo " Run with --update-baseline to create it." >&2
49+
touch "$baseline_tmp"
50+
EMPTY_BASELINE=true
51+
fi
52+
53+
# comm: -13 = lines only in current (new failures), -23 = lines only in baseline (fixed)
54+
new_failures=$(comm -13 "$baseline_tmp" "$current_tmp")
55+
fixed_tests=$(comm -23 "$baseline_tmp" "$current_tmp")
56+
57+
# Report
58+
echo "--- GNU test failure summary ---"
59+
echo "Baseline failures: $(wc -l < "$baseline_tmp")"
60+
echo "Current failures: $(wc -l < "$current_tmp")"
61+
echo ""
62+
63+
if [[ "$EMPTY_BASELINE" == true ]]; then
64+
mkdir -p "$(dirname "$BASELINE")"
65+
{
66+
echo "# Known GNU test failures - format: util/testname"
67+
echo "# Update with: ./scripts/check-new-gnu-failures.sh --update-baseline"
68+
cat "$current_tmp"
69+
} > "$BASELINE"
70+
count=$(wc -l < "$current_tmp")
71+
echo "Initial baseline created: $BASELINE ($count failures recorded)"
72+
exit 0
73+
fi
74+
75+
if [[ -n "$fixed_tests" ]]; then
76+
echo "Tests newly FIXED:"
77+
awk '{print " [FIXED] " $0}' <<< "$fixed_tests"
78+
echo ""
79+
fi
80+
81+
if [[ -n "$new_failures" ]]; then
82+
echo "Tests newly FAILING:"
83+
awk '{print " [NEW FAILURE] " $0}' <<< "$new_failures"
84+
echo ""
85+
count=$(wc -l <<< "$new_failures")
86+
echo "ERROR: $count new test failure(s) detected." >&2
87+
echo " Fix the regression, or if intentional, update the baseline:" >&2
88+
echo " ./scripts/check-new-gnu-failures.sh --update-baseline" >&2
89+
exit 1
90+
fi
91+
92+
echo "No new failures. All current failures are known."
93+
if [[ -n "$fixed_tests" ]]; then
94+
echo "Consider updating the baseline to remove fixed tests:"
95+
echo " ./scripts/check-new-gnu-failures.sh --update-baseline"
96+
fi

scripts/gen-test-helper.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
set -euxo pipefail
4+
5+
cd "$(dirname "$0")/../"
6+
PROJECT_DIR="$(pwd)"
7+
BINARY="$PROJECT_DIR/target/release/util-linux"
8+
9+
if [[ -z "${GNU_PROJECT_DIR:-}" ]]; then
10+
echo "ERROR: GNU_PROJECT_DIR is not set." >&2
11+
echo " Set it to the path of a gnu-util-linux checkout." >&2
12+
exit 2
13+
fi
14+
15+
GNU_TS_DIR="$GNU_PROJECT_DIR/tests/ts"
16+
if [[ ! -d "$GNU_TS_DIR" ]]; then
17+
echo "ERROR: GNU test directory not found: $GNU_TS_DIR" >&2
18+
exit 2
19+
fi
20+
21+
mkdir -p .test-helpers
22+
23+
ours_tmp=$(mktemp)
24+
gnu_tmp=$(mktemp)
25+
trap 'rm -f "$ours_tmp" "$gnu_tmp"' EXIT
26+
27+
for d in "$PROJECT_DIR/src/uu/"*/; do
28+
basename "$d"
29+
done | sort > "$ours_tmp"
30+
31+
for d in "$GNU_TS_DIR/"*/; do
32+
basename "$d"
33+
done | sort > "$gnu_tmp"
34+
35+
comm -12 "$ours_tmp" "$gnu_tmp" > "$PROJECT_DIR/.test-helpers/utils.list"
36+
37+
mapfile -t UTILS < "$PROJECT_DIR/.test-helpers/utils.list"
38+
39+
if [[ ${#UTILS[@]} -eq 0 ]]; then
40+
echo "ERROR: No utilities matched between src/uu/ and $GNU_TS_DIR/" >&2
41+
exit 1
42+
fi
43+
44+
for util in "${UTILS[@]}"; do
45+
cat > ".test-helpers/$util" <<EOF
46+
#!/bin/bash
47+
exec "$BINARY" $util "\$@"
48+
EOF
49+
chmod +x ".test-helpers/$util"
50+
done
51+
52+
echo "Generated wrappers for ${#UTILS[@]} utilities: ${UTILS[*]}"

scripts/run-tests.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
set -euxo pipefail
4+
5+
cd "$(dirname "$0")/../"
6+
PROJECT_DIR="$(pwd)"
7+
8+
cargo build --release
9+
10+
./scripts/gen-test-helper.sh
11+
12+
mapfile -t UTILS < "$PROJECT_DIR/.test-helpers/utils.list"
13+
14+
if [[ ${#UTILS[@]} -eq 0 ]]; then
15+
echo "ERROR: .test-helpers/utils.list is empty; nothing to test." >&2
16+
exit 1
17+
fi
18+
19+
# Clear stale diff files from any previous run
20+
rm -rf "$PROJECT_DIR/.test-helpers/tests/diff"
21+
22+
# Run GNU tests; allow non-zero exit (known failures exist)
23+
set +e
24+
"$GNU_PROJECT_DIR/tests/run.sh" \
25+
--builddir="$PROJECT_DIR/.test-helpers" \
26+
"$@" \
27+
"${UTILS[@]}"
28+
GNU_TEST_EXIT=$?
29+
set -e
30+
31+
[[ $GNU_TEST_EXIT -ne 0 ]] && echo "GNU test runner exited with code $GNU_TEST_EXIT"
32+
33+
./scripts/check-new-gnu-failures.sh

0 commit comments

Comments
 (0)