Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI

on:
workflow_dispatch:
push:
branches: ["master"]
pull_request:
branches: ["master"]

env:
CARGO_TERM_COLOR: always

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --verbose --all-features

checks:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Format
run: cargo fmt -- --check --verbose
- name: Lint
run: cargo clippy --all-targets -- -D warnings
Comment thread
LioQing marked this conversation as resolved.
Outdated
6 changes: 4 additions & 2 deletions coverage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

This directory contains code coverage reports.

The coverage reports are generated using the [run.ps1](./run.ps1) script. To run the script, you need to install [cargo-llvm-cov](https://crates.io/crates/cargo-llvm-cov) and [cargo-nextest](https://crates.io/crates/cargo-nextest).
The coverage reports are generated using the [run.ps1](./run.ps1) (for Windows) and [run.sh](./run.sh) (for Linux/\*nix) scripts.

To run the script, you need to install [cargo-llvm-cov](https://crates.io/crates/cargo-llvm-cov) and [cargo-nextest](https://crates.io/crates/cargo-nextest).

> [!NOTE]
>
> Because the crate requires GPU support, the coverage report is not run in CI.
> Because the crate requires GPU support, the coverage report is not run in CI.
147 changes: 147 additions & 0 deletions coverage/coverage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
macro_rules! cargo {
($arg:literal $(, $fmt_args:expr),* $(,)?) => {{
let cmd_arg = format!($arg, $($fmt_args),*);
let args = cmd_arg.split_whitespace();

println!("cargo {}", cmd_arg);

let status = std::process::Command::new("cargo")
.args(args)
.status()
.expect("failed to execute process");

assert!(status.success(), "command 'cargo {}' failed", cmd_arg);
}};
}

fn main() {
let exe_path = std::env::current_exe().expect("current exe");

let mut manifest_path = exe_path.parent().expect("exe parent").to_path_buf();
while std::fs::read_dir(&manifest_path)
.expect("read dir")
.find(|entry| entry.as_ref().expect("entry").file_name() == "Cargo.toml")
.is_none()
{
manifest_path = manifest_path.parent().expect("parent").to_path_buf();
}

let coverage_path = manifest_path.join("coverage");
let examples_path = manifest_path.join("examples");
let lcov_path = coverage_path.join("lcov.info");
let lcov_path_str = lcov_path.to_str().expect("lcov path");
let badge_path = coverage_path.join("badge.json");
let model_path = examples_path.join("model.ply");
let model_path_str = model_path.to_str().expect("model path");
let output_path = coverage_path.join("output.ply");
let output_path_str = output_path.to_str().expect("output path");

println!("Running coverage...");

cargo!("llvm-cov clean --workspace");

println!("Running 'modify' example");
cargo!(
"llvm-cov run --example modify -- -m {model_path_str} -o {output_path_str} --rgb-or-hsv 0.1 0.9 0.8 --alpha 0.7 --contrast -1.0 --exposure 0.5 --gamma 1.2"
);

println!("Running 'modify' example with '--override-rgb' flag");
cargo!(
"llvm-cov run --example modify -- -m {model_path_str} -o {output_path_str} --override-rgb --rgb-or-hsv 0.7 0.9 0.8 --alpha 0.7 --contrast -1.0 --exposure 0.5 --gamma 1.2"
);

println!("Running 'modify-selection' example");
cargo!(
"llvm-cov run --example modify-selection -- -m {model_path_str} -o {output_path_str} -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --repeat 2 --offset 2.0 0.0 0.0 --contrast -1.0"
);

println!("Running 'modify-selection' example with '--shape Box' flag");
cargo!(
"llvm-cov run --example modify-selection -- -m {model_path_str} -o {output_path_str} -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --shape Box --repeat 2 --offset 2.0 0.0 0.0 --contrast -1.0"
);

println!("Running 'filter-selection' example");
cargo!(
"llvm-cov run --example filter-selection -- -m {model_path_str} -o {output_path_str} -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --repeat 2 --offset 2.0 0.0 0.0"
);

println!("Running 'filter-selection' example with '--shape Box' flag");
cargo!(
"llvm-cov run --example filter-selection -- -m {model_path_str} -o {output_path_str} -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --shape Box --repeat 2 --offset 2.0 0.0 0.0"
);

println!("Running 'custom-modify-selection' example");
cargo!(
"llvm-cov run --example custom-modify-selection -- -m {model_path_str} -o {output_path_str} -p 0.5 0.0 0.2 -r 2.0"
);

println!("Running doctests");
// `--doctests` flag is currently unstable
// cargo!("llvm-cov --no-report --doctests");
cargo!("test --doc");

println!("Running tests");
cargo!("llvm-cov --no-report nextest --all-features");

println!("Generating coverage report");
cargo!("llvm-cov report --lcov --output-path {lcov_path_str}");

println!("Generating badge");

let lcov = std::fs::read_to_string(&lcov_path).expect("read lcov.info");
let mut total: u64 = 0;
let mut covered: u64 = 0;

for line in lcov.lines() {
if !line.starts_with("DA:") {
continue;
}

let mut parts = line[3..].split(',');
let _line_number = parts.next();
let hits_str = parts.next();

let Some(hits_str) = hits_str else {
continue;
};
let Ok(hits) = hits_str.parse::<u64>() else {
continue;
};

total += 1;
if hits != 0 {
covered += 1;
}
}

let badge_percentage: u64 = if total == 0 {
100
} else {
((covered as f32 / total as f32) * 100.0).round() as u64
};

let badge_color = if badge_percentage >= 80 {
"brightgreen"
} else if badge_percentage >= 50 {
"yellow"
} else {
"red"
};

let badge_json = format!(
r#"
{{
"schemaVersion": 1,
"label": "coverage",
"message": "{badge_percentage}%",
"color": "{badge_color}"
}}
"#
);
std::fs::write(&badge_path, badge_json.trim().to_owned() + "\n").expect("write badge.json");

println!("Cleaning up");
std::fs::remove_file(&output_path).expect("remove output.ply");

println!("Done");
}
75 changes: 6 additions & 69 deletions coverage/run.ps1
Original file line number Diff line number Diff line change
@@ -1,72 +1,9 @@
$BASE_DIR = $PSScriptRoot
$EXAMPLES_PATH = "$BASE_DIR/../examples"
$LCOV_PATH = "$BASE_DIR/lcov.info"
$TARGET_DIR = "$PSScriptRoot\..\target\coverage"

echo "Running coverage..."

cargo llvm-cov clean --workspace

echo "Running 'modify' example"
cargo llvm-cov run --example modify -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" --rgb-or-hsv 0.1 0.9 0.8 --alpha 0.7 --contrast "-1.0" --exposure 0.5 --gamma 1.2

echo "Running 'modify' example with '--override-rgb' flag"
cargo llvm-cov run --example modify -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" --override-rgb --rgb-or-hsv 0.7 0.9 0.8 --alpha 0.7 --contrast "-1.0" --exposure 0.5 --gamma 1.2

echo "Running 'modify-selection' example"
cargo llvm-cov run --example modify-selection -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --repeat 2 --offset 2.0 0.0 0.0 --contrast "-1.0"

echo "Running 'modify-selection' example with '--shape Box' flag"
cargo llvm-cov run --example modify-selection -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --shape Box --repeat 2 --offset 2.0 0.0 0.0 --contrast "-1.0"

echo "Running 'filter-selection' example"
cargo llvm-cov run --example filter-selection -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --repeat 2 --offset 2.0 0.0 0.0

echo "Running 'filter-selection' example with '--shape Box' flag"
cargo llvm-cov run --example filter-selection -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" -p 0.5 1.0 0.5 -r 0.2 0.0 0.0 1.0 -s 1 1 1 --shape Box --repeat 2 --offset 2.0 0.0 0.0

echo "Running 'custom-modify-selection' example"
cargo llvm-cov run --example custom-modify-selection -- -m "$EXAMPLES_PATH/model.ply" -o "$BASE_DIR/output.ply" -p 0.5 0.0 0.2 -r 2.0

# `--doctests` flag is currently unstable
# echo "Running doctests"
# cargo llvm-cov --no-report --doctests
cargo test --doc # Run doctests without tracking coverage

echo "Running tests"
cargo llvm-cov --no-report nextest

echo "Generating coverage report"
cargo llvm-cov report --lcov --output-path "$LCOV_PATH"

echo "Generating badge"
$total = 0
$covered = 0
Select-String -Path "$LCOV_PATH" -Pattern "DA:" | ForEach-Object {
if ($_ -match "DA:\d+,(\d+)") {
$total++
if ($matches[1] -ne "0") {
$covered++
}
}
if (!(Test-Path -Path $TARGET_DIR)) {
New-Item -ItemType Directory -Path $TARGET_DIR | Out-Null
}

$badge_percentage = if ($total -eq 0) { 100 } else { [math]::Round(($covered / $total) * 100) }
$badge_color = if ($badge_percentage -ge 80) {
"brightgreen"
} elseif ($badge_percentage -ge 50) {
"yellow"
} else {
"red"
}

"{
`"schemaVersion`": 1,
`"label`": `"coverage`",
`"message`": `"$badge_percentage%`",
`"color`": `"$badge_color`"
}" | Out-File -FilePath "$BASE_DIR/badge.json" -Encoding ascii

echo "Cleaning up"
rm "$BASE_DIR/output.ply"

echo "Done"
rustc "$PSScriptRoot\coverage.rs" -o "$TARGET_DIR\coverage.exe"
& "$TARGET_DIR\coverage.exe"
Remove-Item "$TARGET_DIR\coverage.exe"
17 changes: 17 additions & 0 deletions coverage/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env sh
set -eu

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
TARGET_DIR="$SCRIPT_DIR/../target/coverage"

mkdir -p "$TARGET_DIR"

OUT_BIN="$TARGET_DIR/coverage"

cleanup() {
rm -f "$OUT_BIN"
}
trap cleanup 0

rustc "$SCRIPT_DIR/coverage.rs" -o "$OUT_BIN"
"$OUT_BIN"