Skip to content

Latest commit

Β 

History

History
441 lines (367 loc) Β· 12.1 KB

File metadata and controls

441 lines (367 loc) Β· 12.1 KB

Governance Test Suite - Quick Reference & Structure

πŸ—‚οΈ Test Organization Structure

governance_test.rs (663 lines)
β”‚
β”œβ”€ Phase 1: PROPOSAL LIFECYCLE (12 tests)
β”‚  β”œβ”€ 1.1 Creation (4 tests)
β”‚  β”‚  β”œβ”€ Basic proposal creation with defaults
β”‚  β”‚  β”œβ”€ Custom parameters
β”‚  β”‚  β”œβ”€ Multiple proposals
β”‚  β”‚  └─ Invalid parameters
β”‚  β”‚
β”‚  └─ 1.2 Retrieval (2 tests)
β”‚     β”œβ”€ Existing proposal
β”‚     └─ Non-existent proposal
β”‚
β”œβ”€ Phase 2: VOTING MECHANICS (15 tests)
β”‚  β”œβ”€ 2.1 Vote Casting (5 tests)
β”‚  β”‚  β”œβ”€ Single For vote
β”‚  β”‚  β”œβ”€ For/Against/Abstain votes
β”‚  β”‚  β”œβ”€ Multiple voters
β”‚  β”‚  β”œβ”€ Voting power validation
β”‚  β”‚  └─ Voting after period ends
β”‚  β”‚
β”‚  β”œβ”€ 2.2 Duplicate Prevention (2 tests)
β”‚  β”‚  β”œβ”€ Same voter cannot vote twice
β”‚  β”‚  └─ Different voters OK
β”‚  β”‚
β”‚  └─ 2.3 Threshold Determination (5 tests)
β”‚     β”œβ”€ Threshold met β†’ Passed
β”‚     β”œβ”€ Threshold not met β†’ stays Active
β”‚     β”œβ”€ Exact boundary
β”‚     β”œβ”€ With Against/Abstain votes
β”‚     └─ High threshold (90%+)
β”‚
β”œβ”€ Phase 3: TIMELOCK & EXECUTION (10 tests)
β”‚  β”œβ”€ 3.1 Voting Period (3 tests)
β”‚  β”‚  β”œβ”€ Cannot vote after voting_end
β”‚  β”‚  β”œβ”€ Can vote before voting_end
β”‚  β”‚  └─ Finalize after voting ends
β”‚  β”‚
β”‚  β”œβ”€ 3.2 Execution Timelock (3 tests)
β”‚  β”‚  β”œβ”€ Cannot execute before timelock
β”‚  β”‚  β”œβ”€ Can execute after timelock
β”‚  β”‚  └─ Execute at boundary
β”‚  β”‚
β”‚  └─ 3.3 Execution (4 tests)
β”‚     β”œβ”€ Successful execution
β”‚     β”œβ”€ Cannot re-execute
β”‚     β”œβ”€ Cannot execute Failed
β”‚     └─ Cannot execute Expired
β”‚
β”œβ”€ Phase 4: MULTISIG OPERATIONS (15 tests)
β”‚  β”œβ”€ 4.1 Admin Management (4 tests)
β”‚  β”‚  β”œβ”€ Initialize with default threshold (1)
β”‚  β”‚  β”œβ”€ Set multisig admins
β”‚  β”‚  β”œβ”€ Set multisig threshold
β”‚  β”‚  └─ Prevent impossible thresholds
β”‚  β”‚
β”‚  β”œβ”€ 4.2 Approvals (5 tests)
β”‚  β”‚  β”œβ”€ Admin approves
β”‚  β”‚  β”œβ”€ Same admin cannot approve twice
β”‚  β”‚  β”œβ”€ Different admins accumulate
β”‚  β”‚  β”œβ”€ Non-admin blocked
β”‚  β”‚  └─ Get approvals
β”‚  β”‚
β”‚  └─ 4.3 Execution (6 tests)
β”‚     β”œβ”€ Execute when threshold met
β”‚     β”œβ”€ Cannot execute below threshold
β”‚     β”œβ”€ Execute at boundary
β”‚     β”œβ”€ Only admin can execute
β”‚     β”œβ”€ Specialized proposals
β”‚     └─ Full multisig workflow
β”‚
β”œβ”€ Phase 5: ERROR HANDLING (8 tests)
β”‚  β”œβ”€ 5.1 Authorization (2 tests)
β”‚  β”‚  β”œβ”€ Unauthorized proposal creation
β”‚  β”‚  └─ Multisig auth checks
β”‚  β”‚
β”‚  β”œβ”€ 5.2 Invalid Operations (3 tests)
β”‚  β”‚  β”œβ”€ Vote on non-existent
β”‚  β”‚  β”œβ”€ Execute non-existent
β”‚  β”‚  └─ Invalid vote value
β”‚  β”‚
β”‚  └─ 5.3 State Validation (3 tests)
β”‚     β”œβ”€ State consistency
β”‚     β”œβ”€ Voting power consistency
β”‚     └─ Timestamp ordering
β”‚
β”œβ”€ Phase 6: EVENT VALIDATION (4 tests)
β”‚  β”œβ”€ proposal_created event
β”‚  β”œβ”€ vote_cast event
β”‚  β”œβ”€ proposal_executed event
β”‚  └─ proposal_failed event
β”‚
└─ Phase 7: INTEGRATION SCENARIOS (6 tests)
   β”œβ”€ Complete proposal lifecycle
   β”œβ”€ Proposal fails voting
   β”œβ”€ Multisig with 3 admins (threshold 2)
   β”œβ”€ Multisig with all approvals (threshold 3)
   β”œβ”€ Mixed voting (For/Against/Abstain)
   └─ High-threshold proposal (90%)

Total: 70 tests across 7 phases


πŸ”„ Proposal State Transitions

stateDiagram-v2
    [*] --> Active: create_proposal()

    Active --> Passed: vote() reaches threshold
    Active --> Expired: timestamp > voting_end
    Active --> Failed: mark_proposal_failed()

    Passed --> Executed: execute_proposal() (after timelock)

    Failed --> [*]
    Expired --> [*]
    Executed --> [*]

    note right of Active
        Can receive votes
        voting_end timer active
    end note

    note right of Passed
        Votes met threshold
        Waiting for timelock
    end note

    note right of Executed
        Proposal applied
        Terminal state
    end note
Loading

πŸ—³οΈ Vote Counting Logic

Total Voting Power = 100

Vote Distribution:
  - 55 For    βœ“ (exceeds 50% threshold)
  - 30 Against
  - 15 Abstain

Result: PASSED
Threshold: 50 (basis points 5000)
Actual: 55 (votes_for) >= 50 (required)

Basis Points Reference

100% = 10,000 basis points
90%  = 9,000 basis points
75%  = 7,500 basis points
50%  = 5,000 basis points
25%  = 2,500 basis points
1%   = 100 basis points

⏰ Timelock Sequence

Timeline (timestamps in seconds from now)

t=0         t=voting_period         t=voting_period+execution_timelock
β”‚           β”‚                       β”‚
β”œβ”€ Active   β”œβ”€ Passed              β”œβ”€ Can Execute
β”‚ (votes)   β”‚ (threshold met)       β”‚
β”‚           β”‚                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Phase 1: VOTING PHASE (0 to voting_period)
  - Voters can vote
  - Proposal actively accruing votes
  - Status: Active β†’ Passed (if threshold met)

Phase 2: GRACE PERIOD / TIMELOCK (voting_period to voting_period+execution_timelock)
  - No more votes allowed
  - Cannot execute yet
  - Status: Passed
  - Purpose: Time for stakeholders to review/dispute

Phase 3: EXECUTION WINDOW (after voting_period+execution_timelock)
  - Anyone can execute
  - Status: Passed β†’ Executed
  - Finalized on-chain

πŸ›‘οΈ Test Naming Patterns

Positive Cases (Should Pass)

test_propose_basic_creates_active_proposal()
test_vote_for_increments_votes_for_count()
test_threshold_met_transitions_to_passed()
test_multiple_voters_accumulate_votes()
test_execute_after_timelock_succeeds()
test_multisig_admin_approves_successfully()

Negative Cases (Should Fail/Error)

test_vote_duplicate_returns_already_voted_error()
test_execute_before_timelock_returns_not_ready_error()
test_non_admin_approve_returns_unauthorized_error()
test_invalid_threshold_returns_invalid_proposal_error()
test_vote_zero_power_returns_invalid_error()
test_re_execute_returns_already_executed_error()

Edge Cases (Boundary Testing)

test_threshold_exactly_met_passes_proposal()
test_execute_at_timelock_boundary_succeeds()
test_abort(), high_threshold_9000_basis_points_only_9_of_10()
test_proposal_counter_increment_uniqueness()

πŸ§ͺ Test Setup Template

/// Standard test setup function
fn setup_test_env() -> (Env, Address, Address, u64) {
    let env = Env::default();
    env.mock_all_auths();

    let admin = Address::generate(&env);
    let proposal_id = initialize_governance(&env, admin.clone()).unwrap();

    (env, admin, proposal_id, /* other data */)
}

/// Test with advance time
#[test]
fn test_with_time_advance() {
    let env = Env::default();
    env.mock_all_auths();

    // Initial time
    let initial_timestamp = env.ledger().timestamp();

    // Advance time
    let new_timestamp = initial_timestamp + 3600; // +1 hour
    env.ledger().set(LedgerInfo {
        timestamp: new_timestamp,
        sequence_number: env.ledger().sequence() + 1,
        ..env.ledger()
    });

    // Tests with new timestamp
    assert_eq!(env.ledger().timestamp(), new_timestamp);
}

πŸ“Š Coverage Matrix

Component Tests Coverage Goal Notes
create_proposal 4 100% All code paths
vote 7 100% All vote types + errors
execute_proposal 8 100% All states + timelocks
mark_proposal_failed 2 100% Success + errors
get_proposal 2 100% Hit + miss cases
get_vote 2 100% Hit + miss cases
set_multisig_admins 3 100% Valid + errors
set_multisig_threshold 3 100% Valid + errors
approve_proposal 5 100% All paths
execute_multisig_proposal 6 100% Threshold logic
Events 4 100% All event types
Integration 6 100% Full workflows
Error Handling 8 100% All errors
TOTAL 70 95%+ Comprehensive

πŸ”‘ Key Test Scenarios

Scenario 1: Basic Proposal Lifecycle (6 tests)

1. Create proposal (default params)
2. Voter1 votes For (50 power)
3. Voter2 votes For (50 power)
4. Threshold reached (100 >= 50%) β†’ Passed
5. Wait for timelock (skip time 2 days)
6. Execute proposal β†’ Executed

Scenario 2: Multisig Approval Chain (5 tests)

1. Init 3 admins, threshold=2
2. Create proposal
3. Admin1 approves (1/2)
4. Admin2 approves (2/2) ← Threshold met
5. Admin3 approves (3/2, allowed but not needed)
6. Execute proposal β†’ Executed

Scenario 3: Failed Proposal (4 tests)

1. Create proposal (50% threshold)
2. Voter1 votes For (30 power)
3. Voter2 votes Against (30 power)
4. Time expires (voting_end passed)
5. Vote For (30) < Threshold (50) β†’ Failed
6. Cannot execute Failed proposal

Scenario 4: High Threshold Edge Case (4 tests)

1. Create proposal (90% threshold)
2. 10 voters, each 10 power
3. 9 vote For (90 power)
4. 1 votes Against (10 power)
5. For votes (90) >= Threshold (90) β†’ PASSED
6. Execute after timelock

🚨 Error Codes Reference

pub enum GovernanceError {
    Unauthorized = 1,              // Not authorized for operation
    ProposalNotFound = 2,           // Proposal ID doesn't exist
    ProposalAlreadyExecuted = 3,    // Already executed once
    ProposalAlreadyFailed = 4,      // Proposal failed voting
    ProposalNotReady = 5,           // Timelock not expired
    ThresholdNotMet = 6,            // For votes < threshold
    InvalidProposal = 7,            // Bad parameters
    InvalidVote = 8,                // Bad vote data
    AlreadyVoted = 9,               // Voter voted twice
    VotingPeriodEnded = 10,         // Voting window closed
    ExecutionFailed = 11,           // Execution failed
    InvalidMultisigConfig = 12,     // Bad multisig setup
    InsufficientApprovals = 13,     // Not enough approvals
    ProposalExpired = 14,           // Too old to vote
}

Each error must have dedicated test case(s)


βœ… Checklist for Each Test

for each test:
  βœ“ Setup environment (Env, addresses)
  βœ“ Perform action
  βœ“ Assert expected result
  βœ“ Verify no side effects
  βœ“ Document assumptions
  βœ“ Add NatSpec comment
  βœ“ Name describes exact scenario
  βœ“ Single responsibility (one thing per test)

🎯 Must-Have Comments

Every governance test must include:

/// Tests that [specific behavior] occurs when [specific condition].
///
/// # Setup
/// - [what's initialized]
/// - [addresses created]
/// - [initial state]
///
/// # Test
/// 1. [First action]
/// 2. [Second action]
/// 3. [Expected result]
///
/// # Validation
/// - [What's verified]
/// - [What shouldn't change]
/// - [Error cases handled]
///
/// # Security Note
/// - [Any auth checks]
/// - [State assumptions]
#[test]
fn test_xxx() { ... }

πŸ“ˆ Success Metrics

  • βœ… 70+ tests implemented
  • βœ… 95%+ code coverage
  • βœ… 0 compiler warnings
  • βœ… All tests passing
  • βœ… All error cases covered
  • βœ… All state transitions tested
  • βœ… Integration scenarios complete
  • βœ… Documentation comprehensive
  • βœ… Security assumptions validated
  • βœ… Ready for production

Next Steps:

  1. Open governance_test.rs
  2. Uncomment existing test helpers
  3. Start implementing Phase 1 tests
  4. Follow the timeline: 48 hours
  5. Commit with comprehensive message

Reference: GOVERNANCE_TEST_IMPLEMENTATION_PLAN.md