This document describes the comprehensive test suite for CommitLabs Contracts.
The test suite covers all three contracts in the CommitLabs protocol:
- Commitment NFT Contract - NFT representing liquidity commitments
- Commitment Core Contract - Core contract managing commitment lifecycle
- Attestation Engine Contract - Contract for verifying and recording commitment health
Each contract has its own unit test file:
contracts/commitment_nft/src/tests.rs- NFT contract testscontracts/commitment_core/src/tests.rs- Core contract testscontracts/attestation_engine/src/tests.rs- Attestation engine tests
Cross-contract interaction tests are located in:
tests/integration_tests.rs- Integration tests for all contracts
cargo test# NFT Contract
cd contracts/commitment_nft
cargo test
# Core Contract
cd contracts/commitment_core
cargo test
# Attestation Engine
cd contracts/attestation_engine
cargo testcargo test --test integration_testscargo test -- --nocapturecargo test# NFT Contract
cargo test -p commitment_nft
# Core Contract
cargo test -p commitment_core
# Attestation Engine
cargo test -p attestation_engine
# Integration Tests
cargo test -p integration_testscargo test -- --nocaptureInstall tarpaulin:
cargo install cargo-tarpaulinGenerate coverage report:
cargo tarpaulin --out Html --output-dir coverageView the report:
open coverage/tarpaulin-report.htmlInstall llvm-cov:
cargo install cargo-llvm-covGenerate coverage:
cargo llvm-cov --html --output-dir coverage- ✅ Initialize contract
- ✅ Mint NFT with metadata
- ✅ Get metadata by token ID
- ✅ Get owner of NFT
- ✅ Transfer NFT to new owner
- ✅ Check if NFT is active
- ✅ Settle NFT after maturity
- ✅ Mint with zero duration
- ✅ Mint with maximum values
- ✅ Get metadata for nonexistent token
- ✅ Transfer by non-owner (should fail)
- ✅ Settle before expiration (should fail)
- ✅ Transfer after settlement (should fail)
- ✅ Only admin can mint
- ✅ Only owner can transfer
- ✅ Only admin can settle
- ✅ Mint emits event
- ✅ Transfer emits event
- ✅ Initialize contract
- ✅ Create commitment with rules
- ✅ Get commitment details
- ✅ Update commitment value
- ✅ Check for violations
- ✅ Settle commitment at maturity
- ✅ Early exit with penalty
- ✅ Allocate liquidity
- ✅ Reject zero amount commitments
- ✅ Reject negative amounts
- ✅ Reject zero duration
- ✅ Reject max_loss_percent > 100
- ✅ Detect max loss violation
- ✅ Detect expiration violation
- ✅ Mark commitment as violated
- ✅ Create multiple commitments
- ✅ Update value with maximum values
- ✅ Early exit after settlement (should fail)
- ✅ Allocate with invalid amount (should fail)
- ✅ Only admin can update value (by default)
- ✅ Only owner can early exit
- ✅ Only authorized allocator can allocate
- ✅ Only admin can set authorized allocator
- ✅ Create commitment emits event
- ✅ Update value emits event
- ✅ Initialize contract
- ✅ Record attestation
- ✅ Get all attestations for commitment
- ✅ Get health metrics
- ✅ Verify compliance
- ✅ Record fee generation
- ✅ Record drawdown
- ✅ Calculate compliance score
- ✅ Attest with empty data
- ✅ Record zero drawdown
- ✅ Record maximum drawdown
- ✅ Track multiple commitments
- ✅ Accumulate fees over time
- ✅ Reject zero fee amount
- ✅ Reject negative fee amount
- ✅ Verify compliant commitments
- ✅ Detect non-compliant commitments
- ✅ Calculate score with violations
- ✅ Attest emits event
- ✅ Record fees emits event
- ✅ Record drawdown emits event
- ✅ Create commitment flow (Core + NFT + Attestation)
- ✅ Value update and attestation flow
- ✅ Violation detection flow across contracts
- ✅ Settlement flow with attestations
- ✅ Early exit flow with attestations
Each test file includes a TestFixture helper struct that:
- Sets up the test environment
- Creates necessary addresses
- Initializes contracts
- Provides helper methods for creating test data
Example:
pub struct TestFixture {
pub env: Env,
pub admin: Address,
pub owner: Address,
// ... other fields
}
impl TestFixture {
pub fn setup() -> Self {
// Initialize test environment
}
}- Isolation: Each test is independent and doesn't rely on other tests
- Clear Naming: Test names clearly describe what they're testing
- Edge Cases: Tests cover boundary conditions and error cases
- Access Control: All access control scenarios are tested
- Event Verification: Events are verified where applicable
- Integration: Cross-contract interactions are tested
The tests use Soroban SDK test utilities:
Env::default()- Creates a test environmentAddress::generate()- Generates test addressesset_authorized()andrequire_auth()- Mock authentication
#[test]
fn test_initialize() {
let fixture = TestFixture::setup();
// Test initialization
}#[test]
#[should_panic(expected = "error message")]
fn test_invalid_input() {
// Test that should panic
}#[test]
#[should_panic(expected = "unauthorized")]
fn test_unauthorized_access() {
// Test unauthorized operation
}Tests should be run in CI/CD pipeline:
- On every pull request
- Before merging to main
- Before deployment
- Unit Test Coverage: > 90%
- Integration Test Coverage: All critical flows
- Edge Case Coverage: All boundary conditions
- Error Case Coverage: All error paths
cargo test -- --nocapture --test-threads=1cargo test test_namecargo test pattern- Add gas/resource usage tests
- Add fuzzing tests
- Add property-based tests
- Generate test coverage reports
- Add performance benchmarks
- Tests use mock authentication - no real blockchain required
- Tests run in isolated environments
- All tests should be deterministic
- Tests may need updates as contracts evolve