Test/solver write permission gate 709 - #766
Conversation
Add four tests covering the read-only rejection and read-write success paths in admin_settle_action and admin_cancel_action, as requested in issue MostroP2P#709. Both action handlers call ensure_dispute_finalize_permission which delegates to solver_has_write_permission (category = 2 required). The tests exercise this gate directly using in-memory SQLite with the real migration schema, seeding read-only (category=1) and read-write (category=2) solver fixtures. Tests added: - admin_settle_read_only_solver_is_rejected - admin_settle_read_write_solver_is_allowed - admin_cancel_read_only_solver_is_rejected - admin_cancel_read_write_solver_is_allowed Closes MostroP2P#709
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughStandardizes order-not-found errors to return ChangesError Handling and Permission Gate Tests
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/app/admin_settle.rs (1)
263-297: ⚡ Quick winConsider using the actual disputes migration instead of manual DDL.
The helper manually creates the
disputestable with aCREATE TABLEstatement, while the other tables use migration files viainclude_str!. If adisputesmigration exists inmigrations/, including it would ensure the test schema stays in sync with production.♻️ Recommended approach
Check if a migration file like
migrations/*_disputes.sqlexists. If so, replace lines 282–295 with:- sqlx::query( - r#"CREATE TABLE IF NOT EXISTS disputes ( - id char(36) primary key not null, - order_id char(36) unique not null, - status varchar(10) not null, - order_previous_status varchar(10) not null, - solver_pubkey char(64), - created_at integer not null, - taken_at integer default 0 - )"#, - ) - .execute(&pool) - .await - .unwrap(); + sqlx::query(include_str!("../../migrations/YYYYMMDDHHMMSS_disputes.sql")) + .execute(&pool) + .await + .unwrap();Replace
YYYYMMDDHHMMSSwith the actual migration timestamp.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/admin_settle.rs` around lines 263 - 297, The setup_permission_db helper currently creates the disputes table via manual DDL inside async fn setup_permission_db(); replace that manual CREATE TABLE block with executing the actual disputes migration file (use sqlx::query(include_str!("../../migrations/YYYYMMDDHHMMSS_disputes.sql")).execute(&pool).await.unwrap()) so the test DB schema stays in sync with production; locate the CREATE TABLE for "disputes" in setup_permission_db and swap it to load the corresponding migration file (use the real migration timestamp in the filename).src/app/admin_cancel.rs (1)
244-289: ⚖️ Poor tradeoffConsider extracting shared test helpers to reduce duplication.
The test constants,
setup_permission_db, and seed helpers (lines 244–313) are duplicated betweenadmin_settle.rsandadmin_cancel.rs. Extracting them into a shared test module (e.g.,src/app/test_helpers.rsorsrc/app/admin_test_helpers.rs) would reduce maintenance burden and ensure schema consistency across test suites.♻️ Optional refactor approach
Create
src/app/dispute_test_helpers.rs:#[cfg(test)] pub(crate) mod dispute_test_helpers { pub const DAEMON_PUBKEY: &str = "b1b2c3d4..."; pub const READ_ONLY_SOLVER: &str = "c1b2c3d4..."; pub const READ_WRITE_SOLVER: &str = "d1b2c3d4..."; pub async fn setup_permission_db() -> sqlx::SqlitePool { // ... shared implementation } pub async fn seed_solver(pool: &sqlx::SqlitePool, pubkey: &str, category: i64) { // ... shared implementation } pub async fn seed_dispute(pool: &sqlx::SqlitePool, order_id: uuid::Uuid, solver_pubkey: &str) { // ... shared implementation } }Then import in both test modules:
#[cfg(test)] mod tests { use super::super::dispute_test_helpers::*; // ... tests }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/admin_cancel.rs` around lines 244 - 289, The tests duplicate constants DAEMON_PUBKEY, READ_ONLY_SOLVER, READ_WRITE_SOLVER and the async helper setup_permission_db; extract these into a shared test helper module (e.g., create src/app/dispute_test_helpers.rs with #[cfg(test)] pub(crate) mod dispute_test_helpers) that exposes the three consts and a pub async fn setup_permission_db() plus any seed helpers, then update the tests in admin_cancel.rs and admin_settle.rs to use dispute_test_helpers::{DAEMON_PUBKEY, READ_ONLY_SOLVER, READ_WRITE_SOLVER, setup_permission_db} to remove duplication and keep schema/seed logic centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/app/admin_cancel.rs`:
- Around line 244-289: The tests duplicate constants DAEMON_PUBKEY,
READ_ONLY_SOLVER, READ_WRITE_SOLVER and the async helper setup_permission_db;
extract these into a shared test helper module (e.g., create
src/app/dispute_test_helpers.rs with #[cfg(test)] pub(crate) mod
dispute_test_helpers) that exposes the three consts and a pub async fn
setup_permission_db() plus any seed helpers, then update the tests in
admin_cancel.rs and admin_settle.rs to use dispute_test_helpers::{DAEMON_PUBKEY,
READ_ONLY_SOLVER, READ_WRITE_SOLVER, setup_permission_db} to remove duplication
and keep schema/seed logic centralized.
In `@src/app/admin_settle.rs`:
- Around line 263-297: The setup_permission_db helper currently creates the
disputes table via manual DDL inside async fn setup_permission_db(); replace
that manual CREATE TABLE block with executing the actual disputes migration file
(use
sqlx::query(include_str!("../../migrations/YYYYMMDDHHMMSS_disputes.sql")).execute(&pool).await.unwrap())
so the test DB schema stays in sync with production; locate the CREATE TABLE for
"disputes" in setup_permission_db and swap it to load the corresponding
migration file (use the real migration timestamp in the filename).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ded35d11-72fc-44b9-8636-65584ef3c852
📒 Files selected for processing (5)
src/app/admin_cancel.rssrc/app/admin_settle.rssrc/app/admin_take_dispute.rssrc/app/dispute.rssrc/util.rs
Replace the inline CREATE TABLE disputes block in setup_permission_db with include_str! on the existing migrations/20230928145530_disputes.sql, so the test schema stays in sync with production automatically. Addresses CodeRabbit nitpick on PR MostroP2P#766.
|
Maybe we can reuse this shorter form for setting up migrations in all files to complete PR: async fn create_test_pool() -> SqlitePool {
let pool = SqlitePool::connect("sqlite::memory:").await.unwrap();
sqlx::migrate!().run(&pool).await.unwrap();
pool
}The logic of test is ok! |
Replace the manual four-file migration sequence with sqlx::migrate!() which runs all migrations in order automatically. This keeps the test schema in sync with production without requiring manual updates when new migrations are added. Addresses review suggestion by arkanoider on PR MostroP2P#766.
|
Thanks @arkanoider for the insight, done in 8a39743. Replaced the manual four-file migration sequence with |
Summary
Closes #709.
Adds four behavioral tests covering the read-only rejection and read-write success paths in
admin_settle_actionandadmin_cancel_action, as requested by @grunch during review of PR #708.Approach
Both action handlers call
ensure_dispute_finalize_permissionbefore any Lightning operations. The tests exercise this gate directly rather than calling the full action handler, which would require a mock LND connector. This covers the exact authorization boundary described in the issue while keeping the fixtures minimal and deterministic.Each test seeds an in-memory SQLite database with the real migration schema, inserts a solver and an assigned dispute, then asserts the permission gate returns the correct result.
Tests added
src/app/admin_settle.rsadmin_settle_read_only_solver_is_rejected: solver withcategory=1receivesMostroCantDo(NotAuthorized)admin_settle_read_write_solver_is_allowed: solver withcategory=2passes the gatesrc/app/admin_cancel.rsadmin_cancel_read_only_solver_is_rejected: solver withcategory=1receivesMostroCantDo(NotAuthorized)admin_cancel_read_write_solver_is_allowed: solver withcategory=2passes the gateTest results
cargo fmt,cargo clippy, andcargo testall green.Summary by CodeRabbit
Tests
Bug Fixes