diff --git a/.kiro/specs/insurance-payment-time-tests/.config.kiro b/.kiro/specs/insurance-payment-time-tests/.config.kiro deleted file mode 100644 index dad3f83..0000000 --- a/.kiro/specs/insurance-payment-time-tests/.config.kiro +++ /dev/null @@ -1 +0,0 @@ -{"specId": "4c5c3a54-ee47-4f29-a1a0-bfbb8e825f9c", "workflowType": "requirements-first", "specType": "feature"} \ No newline at end of file diff --git a/docs/regression-testing-policy.md b/docs/regression-testing-policy.md new file mode 100644 index 0000000..a74bec1 --- /dev/null +++ b/docs/regression-testing-policy.md @@ -0,0 +1,18 @@ +# Regression Testing Policy + +- Every bug fix must include a failing regression test that reproduces the issue and passes with the fix. +- Place new regression tests alongside the affected crate’s tests or under integration_tests in a dedicated regression_tests module. +- Tests must be minimal, deterministic, and focus on the fixed behavior. +- Do not modify production code solely to accommodate tests. +- Link the test to its issue or PR number in the commit message. +- CI must block merges for bug-fix PRs without a corresponding regression test. + +Scope +- Applies to all crates in this workspace. +- Includes unit, integration, and property-based tests where appropriate. + +Process +- Reproduce: Write a test that fails against the buggy behavior. +- Fix: Implement the code change. +- Verify: Ensure the new test and the full suite pass locally and in CI. +- Document: Reference the issue/PR in the test commit message. diff --git a/integration_tests/tests/regression_tests.rs b/integration_tests/tests/regression_tests.rs new file mode 100644 index 0000000..00971f3 --- /dev/null +++ b/integration_tests/tests/regression_tests.rs @@ -0,0 +1,82 @@ +#![cfg(test)] + +use soroban_sdk::{testutils::Address as _, Address, Env, String as SorobanString}; + +use bill_payments::{BillPayments, BillPaymentsClient}; +use insurance::{Insurance, InsuranceClient}; +use remittance_split::{RemittanceSplit, RemittanceSplitClient}; + +mod regression_tests { + use super::*; + + #[test] + #[should_panic(expected = "overflow")] + fn bill_payments_total_unpaid_overflow_panics() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = env.register_contract(None, BillPayments); + let client = BillPaymentsClient::new(&env, &contract_id); + let owner = Address::generate(&env); + + let amount = i128::MAX / 2 + 1000; + + client.create_bill( + &owner, + &SorobanString::from_str(&env, "Bill1"), + &amount, + &1_000_000u64, + &false, + &0u32, + &SorobanString::from_str(&env, "XLM"), + ); + + client.create_bill( + &owner, + &SorobanString::from_str(&env, "Bill2"), + &amount, + &1_000_000u64, + &false, + &0u32, + &SorobanString::from_str(&env, "XLM"), + ); + + let _ = client.get_total_unpaid(&owner); + } + + #[test] + fn remittance_split_checked_arithmetic_overflow_returns_error() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = env.register_contract(None, RemittanceSplit); + let client = RemittanceSplitClient::new(&env, &contract_id); + let owner = Address::generate(&env); + + client.initialize_split(&owner, &0u64, &50u32, &30u32, &15u32, &5u32); + + let overflow_amount = i128::MAX / 50 + 1; + let result = client.try_calculate_split(&overflow_amount); + assert!(result.is_err()); + } + + #[test] + fn insurance_non_owner_cannot_pay_premium() { + let env = Env::default(); + env.mock_all_auths(); + let contract_id = env.register_contract(None, Insurance); + let client = InsuranceClient::new(&env, &contract_id); + let owner = Address::generate(&env); + let other = Address::generate(&env); + + let policy_id = client.create_policy( + &owner, + &SorobanString::from_str(&env, "Policy"), + &SorobanString::from_str(&env, "health"), + &100i128, + &10_000i128, + ); + + let res = client.try_pay_premium(&other, &policy_id); + assert!(res.is_err()); + } +} +