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
59 changes: 59 additions & 0 deletions .config/make/coverage.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## —— Coverage (cargo-llvm-cov) ----------------------------------------------------------------
##
## Prerequisites:
## cargo install cargo-llvm-cov
## rustup component add llvm-tools-preview
##
## Doctests are not run under coverage (they require nightly). Use stable for unit/e2e coverage.
## Optional: use COVERAGE_OUTPUT_DIR to change report dir (default: target/coverage)
##
## Use BFD linker for coverage builds when available to avoid LLD duplicate-symbol
## errors with -C instrument-coverage (e.g. arrow_array/arrow_arith in datafusion).
## If ld.bfd is not found, no linker override is set (may hit duplicate symbol on LLD).
## Override: make coverage-unit COVERAGE_RUSTFLAGS="-C link-arg=-fuse-ld=bfd"

COVERAGE_RUSTFLAGS_DEFAULT := $(shell command -v ld.bfd >/dev/null 2>&1 && echo '-C link-arg=-fuse-ld=bfd' || true)
COVERAGE_RUSTFLAGS ?= $(COVERAGE_RUSTFLAGS_DEFAULT)
COVERAGE_OUTPUT_DIR ?= target/coverage
COVERAGE_E2E_DIR := $(COVERAGE_OUTPUT_DIR)/e2e
## LCOV file for editor integration (Cursor/VS Code Coverage Gutters). Default: repo root.
COVERAGE_LCOV_PATH ?= lcov.info

.PHONY: coverage-check
coverage-check: ## Verify cargo-llvm-cov and llvm-tools are available
@cargo llvm-cov --version >/dev/null 2>&1 || (echo "Install: cargo install cargo-llvm-cov && rustup component add llvm-tools-preview"; exit 1)

.PHONY: coverage-deps
coverage-deps: ## Install cargo-llvm-cov and llvm-tools-preview if missing
@command -v cargo >/dev/null 2>&1 || (echo "cargo not found. Ensure Rust is installed and in PATH."; exit 1)
@cargo llvm-cov --version >/dev/null 2>&1 || \
(echo "Installing coverage tools..."; cargo install cargo-llvm-cov && rustup component add llvm-tools-preview)
@cargo llvm-cov --version >/dev/null 2>&1 || (echo "Install failed. Run: cargo install cargo-llvm-cov && rustup component add llvm-tools-preview"; exit 1)
Comment on lines +24 to +31
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

coverage-check/coverage-deps claim to verify/install both cargo-llvm-cov and llvm-tools-preview, but the logic only checks whether cargo llvm-cov exists. If a developer already has cargo-llvm-cov installed but is missing llvm-tools-preview (or rustup itself), these targets can still pass the dependency step and then fail later during cargo llvm-cov test/report. Update the checks to also verify the LLVM tools are available (e.g., via rustup which llvm-profdata/llvm-cov) and make rustup component add llvm-tools-preview run when the component is missing, regardless of whether cargo-llvm-cov is already installed.

Suggested change
@cargo llvm-cov --version >/dev/null 2>&1 || (echo "Install: cargo install cargo-llvm-cov && rustup component add llvm-tools-preview"; exit 1)
.PHONY: coverage-deps
coverage-deps: ## Install cargo-llvm-cov and llvm-tools-preview if missing
@command -v cargo >/dev/null 2>&1 || (echo "cargo not found. Ensure Rust is installed and in PATH."; exit 1)
@cargo llvm-cov --version >/dev/null 2>&1 || \
(echo "Installing coverage tools..."; cargo install cargo-llvm-cov && rustup component add llvm-tools-preview)
@cargo llvm-cov --version >/dev/null 2>&1 || (echo "Install failed. Run: cargo install cargo-llvm-cov && rustup component add llvm-tools-preview"; exit 1)
@command -v cargo >/dev/null 2>&1 || (echo "cargo not found. Ensure Rust is installed and in PATH."; exit 1)
@command -v rustup >/dev/null 2>&1 || (echo "rustup not found. Install Rust via https://rustup.rs/"; exit 1)
@cargo llvm-cov --version >/dev/null 2>&1 || (echo "cargo-llvm-cov not found. Install: cargo install cargo-llvm-cov"; exit 1)
@rustup which llvm-profdata >/dev/null 2>&1 || (echo "llvm-tools-preview (llvm-profdata) not found. Run: rustup component add llvm-tools-preview"; exit 1)
@rustup which llvm-cov >/dev/null 2>&1 || (echo "llvm-tools-preview (llvm-cov) not found. Run: rustup component add llvm-tools-preview"; exit 1)
.PHONY: coverage-deps
coverage-deps: ## Install cargo-llvm-cov and llvm-tools-preview if missing
@command -v cargo >/dev/null 2>&1 || (echo "cargo not found. Ensure Rust is installed and in PATH."; exit 1)
@command -v rustup >/dev/null 2>&1 || (echo "rustup not found. Install Rust via https://rustup.rs/"; exit 1)
@cargo llvm-cov --version >/dev/null 2>&1 || \
(echo "Installing cargo-llvm-cov..."; cargo install cargo-llvm-cov)
@rustup which llvm-profdata >/dev/null 2>&1 || \
(echo "Installing llvm-tools-preview via rustup..."; rustup component add llvm-tools-preview)
@cargo llvm-cov --version >/dev/null 2>&1 && \
rustup which llvm-profdata >/dev/null 2>&1 && \
rustup which llvm-cov >/dev/null 2>&1 || \
(echo "Install failed. Run: cargo install cargo-llvm-cov && rustup component add llvm-tools-preview"; exit 1)

Copilot uses AI. Check for mistakes.

.PHONY: coverage-unit
coverage-unit: coverage-deps ## Run unit/integration tests with coverage (excludes e2e_test)
@echo "📊 Running unit/integration coverage..."
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov test --workspace --exclude e2e_test --no-fail-fast --no-report
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov report --lcov --output-path "$(COVERAGE_LCOV_PATH)"
Comment on lines +36 to +39
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The coverage targets overwrite RUSTFLAGS with COVERAGE_RUSTFLAGS, which drops any user-provided RUSTFLAGS (e.g., for target-specific linking or feature cfgs). Consider appending to the existing RUSTFLAGS (or only setting it when it’s empty) so coverage runs don’t unexpectedly change a developer’s environment.

Copilot uses AI. Check for mistakes.
@echo "📄 LCOV (editor): $(COVERAGE_LCOV_PATH)"

.PHONY: coverage-e2e
coverage-e2e: coverage-deps ## Run e2e tests with coverage (e2e_test crate only)
@echo "📊 Running e2e coverage..."
@mkdir -p "$(COVERAGE_E2E_DIR)"
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov test -p e2e_test --no-fail-fast --no-report
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov report -p e2e_test --lcov --output-path "$(COVERAGE_E2E_DIR)/lcov.info"
@echo "📄 LCOV: $(COVERAGE_E2E_DIR)/lcov.info"

.PHONY: coverage-combined
coverage-combined: coverage-deps ## Run all tests (unit + e2e) with a single combined coverage report
@echo "📊 Running combined coverage (unit + e2e)..."
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov test --workspace --no-fail-fast --no-report
export RUSTFLAGS="$(COVERAGE_RUSTFLAGS)" && \
cargo llvm-cov report --lcov --output-path "$(COVERAGE_LCOV_PATH)"
@echo "📄 LCOV (editor): $(COVERAGE_LCOV_PATH)"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
lcov.info
.DS_Store
.idea
.vscode
Expand Down
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ How to use me:
make test # Run tests
make pre-commit # Run all pre-commit checks

📚 Documentation:
make doc # Generate Rust API docs (target/doc)
make doc-serve # Serve docs at http://127.0.0.1:8765/ (links work)
make doc-open # Generate docs, serve, and open in browser

📊 Coverage (requires: cargo install cargo-llvm-cov; rustup component add llvm-tools-preview):
make coverage-unit # Unit/integration coverage (excludes e2e_test)
make coverage-e2e # E2E coverage (e2e_test crate)
make coverage-combined # All tests, single combined report

🚀 Quick Start:
make build # Build RustFS binary
make docker-dev-local # Build development Docker image (local)
Expand Down
88 changes: 88 additions & 0 deletions doc/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Development Guide

This page covers building, testing, and running quality checks for RustFS. For code formatting rules and PR expectations, see [CONTRIBUTING.md](../CONTRIBUTING.md).

## Prerequisites

- Rust (see root [Cargo.toml](../Cargo.toml) `rust-version`)
- For full quality gates: `make` (see [.config/make/](../.config/make/) and root [Makefile](../Makefile))

## Build

```bash
# Build the RustFS binary
make build
# or
cargo build --release
```

## Testing

```bash
# Run tests
make test
# or
cargo test --all-targets
```

## Code Quality (Mandatory Before Commit)

Run all pre-commit checks:

```bash
make pre-commit
```

If `make` is unavailable, run the equivalent steps from [.config/make/](../.config/make/). Typical steps:

- Format: `cargo fmt --all` and `cargo fmt --all --check`
- Lint: `cargo clippy --all-targets --all-features -- -D warnings`
- Check: `cargo check --all-targets`
- Tests: `cargo test --all-targets`

See [CONTRIBUTING.md](../CONTRIBUTING.md) for detailed formatting and clippy rules.

## Make Targets

- `make help` — Main help and categories
- `make help-build` — Build-related targets
- `make help-docker` — Docker and image targets
- `make fmt` / `make fmt-check` — Format and verify
- `make clippy` — Clippy
- `make check` — Compilation check
Comment on lines +51 to +52
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

This doc lists make clippy and make check, but the Make targets in .config/make/ are named clippy-check and compilation-check (and there is no check/clippy alias). Update these target names (or add aliases in the Makefiles) so the documentation matches what actually works.

Suggested change
- `make clippy` — Clippy
- `make check` — Compilation check
- `make clippy-check` — Clippy
- `make compilation-check` — Compilation check

Copilot uses AI. Check for mistakes.
- `make test` — Tests
- `make pre-commit` — All checks required before commit
- `make doc` — Generate Rust API documentation (HTML in `target/doc`)
- `make doc-serve` — Generate docs and serve at http://127.0.0.1:8765/ (all links work; Ctrl+C to stop)
- `make doc-open` — Generate docs, start local server, and open browser (use this so cross-crate links work)

## Coverage

Coverage uses `cargo-llvm-cov`. Install once:

```bash
cargo install cargo-llvm-cov
rustup component add llvm-tools-preview
```

Then run:

- `make coverage-unit` — Unit and integration tests (all crates except `e2e_test`). Writes LCOV to `lcov.info` (repo root).
- `make coverage-e2e` — E2E tests only (`e2e_test` crate). Writes LCOV to `target/coverage/e2e/lcov.info`.
- `make coverage-combined` — All tests in one run. Writes LCOV to `lcov.info` (repo root).

Use the LCOV file in Cursor or VS Code with a coverage extension (e.g. Coverage Gutters) for inline coverage; the extension looks for `lcov.info` in the workspace by default. Override the path with `COVERAGE_LCOV_PATH`, or for e2e use `COVERAGE_OUTPUT_DIR`.

Doctests are not included in coverage (they require the nightly toolchain).

Coverage builds use the BFD linker (`-fuse-ld=bfd`) by default to avoid LLD duplicate-symbol errors with `-C instrument-coverage` (e.g. with datafusion/arrow deps). This requires binutils (e.g. `ld.bfd`) on the system. To use another linker, set `COVERAGE_RUSTFLAGS` when invoking the target, e.g. `make coverage-unit COVERAGE_RUSTFLAGS=`.

## CI

Quality gates are defined in [.github/workflows/ci.yml](../.github/workflows/ci.yml). Keep local checks aligned with CI so `make pre-commit` matches what runs on the branch.

## Branch and PR Baseline

- Use feature branches from latest `main`.
- Follow [Conventional Commits](https://www.conventionalcommits.org/), subject ≤ 72 characters.
- Use [.github/pull_request_template.md](../.github/pull_request_template.md) for PRs; use `N/A` for non-applicable sections.
Loading