Skip to content

Tests and CI: run the root suite on PRs, make skips visible, assert on output, fix tautological tests, tighten CI hygiene #250

Description

@pierre-warnier

Findings on the test suite, CI and build system.

Coverage that does not exist

  • The PAM path had no automated coverage until the e2e image was repaired; keep it that way and add #[cfg(feature = "pam")] tests that drive authenticate_caller against pam_permit/pam_deny stacks in the Docker images.
  • ~120 of 162 integration tests return silently when not root and are reported ok; the only root run (Docker matrix) is if: github.event_name == 'push', so on a pull request about 75 % of the suite does not execute. Run the matrix on PRs (each job is under 4 min), make skips visible (SHADOW_TEST_REQUIRE_ROOT=1 in the containers turns a skip into a failure), and un-gate the pwck/grpck/chage tests that never needed root.
  • The Docker matrix runs without --features pam; root+PAM is never unit-tested.
  • Tests call uumain() in-process and assert on nothing but exit codes: zero stdout/stderr assertions across the suite, so "bit-for-bit identical output" is unverified. Spawn CARGO_BIN_EXE_shadow-rs instead, which also stops harden_process, setuid(0), Landlock and umask changes from leaking between tests in one process.
  • Tautological tests: test_chage.rs and test_chpasswd.rs never invoke their tool (they set a shadow field and read it back); test_pwck accepts 0 || 2; test_chsh passes because PAM fails first; test_chfn discards its fixture; test_passwd discards eight return codes and races four threads on a PID-keyed lock. Rewrite against spawned binaries once chage/chpasswd/chfn/chsh have a --prefix.
  • No test that the multicall binary registers every tool (one table now drives dispatch and --list; a test that spawns shadow-rs <tool> --help for all fourteen names closes it).
  • Fuzz targets are not built in CI, have no subid target, and assert only "no panic"; add parse→Display→parse and no-separator invariants. The corpus is tracked but gitignored — decide.

CI

  • No permissions: blocks; actions pinned by tag, not digest (helpers:pinGitHubActionDigests in Renovate).
  • MSRV job runs cargo check --workspace without --all-targets/--all-features; completions and (until shadow-core: keep ownership on rewrite, refuse field injection, never abort on '..' #238) selinux were compiled by nobody. Add an --all-features clippy pass.
  • no-ai-traces.sh: the regex is not word-boundaried (llm matches smallmap, anthropic matches philanthropic), so it will block legitimate PRs touching CONTRIBUTING.md's tooling policy paragraph, and it misses gpt-4o, cursor, aider, co-authored-by: *[bot]. ${{ github.base_ref }} is interpolated into run:; pass it through env:.
  • audit.yml duplicates the deny job; keep one scheduled advisory check.
  • Two hook systems (hooks/ in Docker vs .pre-commit-config.yaml on the host with a different feature set); pre-push hook runs the full multi-distro suite and gets bypassed #231 already tracks the pre-push cost. Keep one, and encode the CI commands in make check/make test so README, CONTRIBUTING, hooks and ci.yml stop repeating them.

Build and dependencies

  • clap/derive is enabled and unused; it alone pulls clap_derive + syn 3 next to syn 2 and is why deny.toml skips the duplicate.
  • Makefile installs all fourteen tools into $(PREFIX)/sbin; GNU puts passwd chage chfn chsh newgrp in bin (non-root users rarely have sbin in PATH). make test runs without pam while install ships it.
  • shadow-rs.spec (version 0.2.0, %files lists a binary make install no longer produces) and debian/ are stale and would not build; tests/gnu-compat.sh compares full output for two commands only. Fix or delete.
  • rust:latest, rust:alpine, fedora:latest and get.nexte.st/latest are unpinned (nextest is never used); toolchain drift lands on main with no PR signal.
  • deny.toml allows MPL-2.0, ISC, BSD-2-Clause, CC0, Zlib that nothing uses — tighten to the graph; document that self_cell is accepted under its Apache option; unknown-registry/unknown-gitdeny.
  • Fourteen [[test]] binaries each linking all fourteen crates, with fn run, read_shadow, setup_prefix … duplicated up to 14×; the uutils layout (tests/tests.rs + mod by_util + a real common) is the fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions