Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
62a1d40
chore: add cargo-tarpaulin config with 95% minimum coverage threshold
clintjeff2 Feb 23, 2026
6e42334
chore: add coverage.sh script to run tarpaulin and report results loc…
clintjeff2 Feb 23, 2026
3ea7e2d
ci: add coverage workflow to enforce 95% minimum on push and pull req…
clintjeff2 Feb 23, 2026
dabda32
test: expand vault test suite from 2 to 8 cases achieving 100% line c…
clintjeff2 Feb 23, 2026
ec2b750
docs: add test coverage section documenting local and CI usage
clintjeff2 Feb 23, 2026
390efa3
chore: exclude coverage/ output directory from version control
clintjeff2 Feb 23, 2026
b0229e4
Merge branch 'main' into main
clintjeff2 Feb 24, 2026
5024b15
fix: fixed merge conflict
clintjeff2 Feb 24, 2026
f5c17c6
fix: fixed test to cover 95%
clintjeff2 Feb 24, 2026
c312558
fix: fixed test to cover 95%
clintjeff2 Feb 24, 2026
dae49c0
fix: add GitHub Actions permissions and apply cargo fmt
clintjeff2 Feb 24, 2026
f3eb561
merged
clintjeff2 Feb 24, 2026
b2bf252
fix: fixed test to cover 95%
clintjeff2 Feb 24, 2026
b94ca35
live test checks
clintjeff2 Feb 24, 2026
a10d4ed
github permissions
clintjeff2 Feb 24, 2026
96f8c1a
live testing
clintjeff2 Feb 24, 2026
29a5bb3
live fixing
clintjeff2 Feb 24, 2026
4c8c79f
live fixing
clintjeff2 Feb 24, 2026
c1f361b
fix: final test coverage checks
clintjeff2 Feb 24, 2026
ba76a81
Merge branch 'main' into main
clintjeff2 Feb 25, 2026
7a91454
chore: update gitignore
clintjeff2 Feb 26, 2026
a9e191e
chore: add rand dev-dependency for fuzz tests
clintjeff2 Feb 26, 2026
af118ba
fix: persist revenue_pool and max_deduct in vault init
clintjeff2 Feb 26, 2026
a3fe2a9
test: large balance and large deduct
clintjeff2 Feb 26, 2026
e72bda6
docs: add pull request message for issue 32
clintjeff2 Feb 26, 2026
5085a17
chore: add per-file commit script
clintjeff2 Feb 26, 2026
c0177ff
merged
clintjeff2 Feb 26, 2026
93da9af
restored tests
clintjeff2 Feb 26, 2026
0f8f8ed
fix: fixed test coverage to above 95%
clintjeff2 Feb 26, 2026
2739757
removed unwanted files
clintjeff2 Feb 26, 2026
0891a1a
Merge branch 'main' into large-balance-deduct
greatest0fallt1me Feb 26, 2026
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
74 changes: 74 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Test Coverage

# Run on every push to the main branches and on every pull-request targeting them.
# Also triggers manually from the Actions UI (workflow_dispatch).
on:
push:
branches: [main, master, "chore/coverage-report"]
pull_request:
branches: [main, master]
workflow_dispatch:

jobs:
coverage:
name: "Cargo Test Coverage (≥ 95 %)"
runs-on: ubuntu-latest

steps:
# -----------------------------------------------------------------------
# 1. Source
# -----------------------------------------------------------------------
- name: Checkout repository
uses: actions/checkout@v4

# -----------------------------------------------------------------------
# 2. Rust toolchain — stable is sufficient for Soroban unit tests
# -----------------------------------------------------------------------
- name: Install Rust stable toolchain
uses: dtolnay/rust-toolchain@stable

# -----------------------------------------------------------------------
# 3. Cache — speeds up subsequent runs considerably
# -----------------------------------------------------------------------
- name: Cache Cargo registry and build artefacts
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
# Key rotates when Cargo.lock changes; falls back to any prior entry.
key: ${{ runner.os }}-cargo-tarpaulin-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-tarpaulin-
${{ runner.os }}-cargo-

# -----------------------------------------------------------------------
# 4. Install cargo-tarpaulin via the taiki-e installer — faster than
# `cargo install` because it downloads a pre-built binary.
# -----------------------------------------------------------------------
- name: Install cargo-tarpaulin
uses: taiki-e/install-action@v2
with:
tool: cargo-tarpaulin

# -----------------------------------------------------------------------
# 5. Run coverage
# Configuration lives in tarpaulin.toml (workspace root).
# A non-zero exit here means coverage fell below the 95 % threshold —
# this deliberately fails the workflow.
# -----------------------------------------------------------------------
- name: Run test coverage
run: cargo tarpaulin --config tarpaulin.toml

# -----------------------------------------------------------------------
# 6. Upload HTML + XML report as a downloadable workflow artefact.
# Always runs so the report is available even when coverage fails.
# -----------------------------------------------------------------------
- name: Upload coverage report artefact
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 30
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ Cargo.lock
.env
.env.*
/target/
/target_local/
/target_local/
.md-*
hidden
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,67 @@ All tests use `#[should_panic]` assertions for guaranteed validation. This resol
## Development

Use one branch per issue or feature (e.g. `test/minimum-deposit-rejected`, `docs/vault-gas-notes`) to keep PRs small and reduce merge conflicts. Run `cargo fmt`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test` before pushing.
<<<<<<< HEAD

## Test coverage

The project enforces a **minimum of 95 % line coverage** on every push and pull-request via GitHub Actions.

### Run coverage locally

```bash
# First time only — the script auto-installs cargo-tarpaulin if absent
./scripts/coverage.sh
```

The script will:

1. Check for `cargo-tarpaulin`; install it automatically if it is missing.
2. Run all tests with instrumentation according to `tarpaulin.toml`.
3. Exit with a non-zero code if coverage drops below 95 %.
4. Write reports to the `coverage/` directory (git-ignored).

| Report file | Description |
| -------------------------------- | ----------------------------------------------- |
| `coverage/tarpaulin-report.html` | Interactive per-file view — open in any browser |
| `coverage/cobertura.xml` | Cobertura XML consumed by CI |

> **Tip:** You can also run `cargo tarpaulin` directly from the workspace root;
> the settings in `tarpaulin.toml` are picked up automatically.

### CI enforcement

`.github/workflows/coverage.yml` runs on every push and pull-request.
It installs tarpaulin, runs coverage, uploads the HTML report as a downloadable
artefact, and posts a coverage summary table as a PR comment.
A result below 95 % causes the workflow — and the required status check — to fail.
=======
>>>>>>> b0229e42e4d4517da9f548ea3e374a5886304bf2

## Project layout

```
callora-contracts/
├── .github/workflows/
│ └── ci.yml # CI: fmt, clippy, test, WASM build
<<<<<<< HEAD
├── Cargo.toml # Workspace and release profile
├── BENCHMARKS.md # Vault operation gas/cost notes
├── EVENT_SCHEMA.md # Event names, topics, and payload types
├── UPGRADE.md # Vault upgrade and migration path
├── tarpaulin.toml # cargo-tarpaulin config (≥ 95 % enforced)
├── scripts/
│ └── coverage.sh # One-command local coverage runner
├── .github/
│ └── workflows/
│ └── coverage.yml # CI: enforces 95 % on every push / PR
└── contracts/
└── vault/
├── Cargo.toml
└── src/
├── lib.rs # Contract logic
└── test.rs # Unit tests (covers all code paths)
=======
├── Cargo.toml # Workspace and release profile
├── BENCHMARKS.md # Vault operation gas/cost notes
├── EVENT_SCHEMA.md # Event names, topics, and payload types
Expand All @@ -111,6 +165,7 @@ callora-contracts/
│ ├── lib.rs # Settlement contract
│ └── test.rs # Unit tests
└── README.md
>>>>>>> b0229e42e4d4517da9f548ea3e374a5886304bf2
```

## Security Notes
Expand Down
31 changes: 31 additions & 0 deletions contracts/revenue_pool/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,34 @@ fn batch_distribute_unauthorized_panics() {
let payments = vec![&env, (dev1.clone(), 300)];
client.batch_distribute(&attacker, &payments);
}

#[test]
fn get_admin_before_init_fails() {
let env = Env::default();
let (_, client) = create_pool(&env);
let result = client.try_get_admin();
assert!(result.is_err(), "expected error when pool not initialized");
}

#[test]
fn balance_before_init_fails() {
let env = Env::default();
let (_, client) = create_pool(&env);
let result = client.try_balance();
assert!(result.is_err(), "expected error when pool not initialized");
}

#[test]
fn set_admin_unauthorized_fails() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let intruder = Address::generate(&env);
let new_admin = Address::generate(&env);
let (_, client) = create_pool(&env);
let (usdc, _, _) = create_usdc(&env, &admin);

client.init(&admin, &usdc);
let result = client.try_set_admin(&intruder, &new_admin);
assert!(result.is_err(), "expected error for unauthorized set_admin");
}
Loading
Loading