소스 검색

Add test for duplicate payment ID rejection in mint quotes

Adds comprehensive test coverage to verify that duplicate payment IDs are
properly rejected when incrementing mint quote amounts, preventing
double-payment scenarios.

Changes:
- Added reject_duplicate_payment_ids test function to validate payment ID
  uniqueness
- Test verifies that attempting to increment amount with duplicate payment_id
  returns Error::Duplicate
- Test confirms that quote amount is not incremented when duplicate is rejected
- Test validates that different payment IDs can successfully increment the
  amount
- Updated mint_db_test macro to include the new test
- Simplified keyset duplicate insertion test to expect success (consistent
  behavior)

The test ensures database integrity by preventing the same payment from being
counted multiple times toward a mint quote's total paid amount.
Cesar Rodas 1 개월 전
부모
커밋
df1b636e4e

+ 2 - 5
crates/cdk-common/src/database/mint/test/keys.rs

@@ -73,11 +73,8 @@ where
     // Both behaviors are acceptable
     let mut tx = KeysDatabase::begin_transaction(&db).await.unwrap();
     let result = tx.add_keyset_info(keyset_info).await;
-    if result.is_ok() {
-        tx.commit().await.unwrap();
-    } else {
-        tx.rollback().await.unwrap();
-    }
+    assert!(result.is_ok());
+    tx.commit().await.unwrap();
 
     // Verify keyset still exists
     let retrieved = db.get_keyset_info(&keyset_id).await.unwrap();

+ 67 - 0
crates/cdk-common/src/database/mint/test/mint.rs

@@ -1272,3 +1272,70 @@ where
     assert_eq!(retrieved_sig.c, sig.c);
     tx.commit().await.unwrap();
 }
+
+/// Test that duplicate payment IDs are rejected
+pub async fn reject_duplicate_payment_ids<DB>(db: DB)
+where
+    DB: Database<Error> + KeysDatabase<Err = Error>,
+{
+    use crate::database::mint::test::unique_string;
+
+    let mint_quote = MintQuote::new(
+        None,
+        "".to_owned(),
+        cashu::CurrencyUnit::Sat,
+        None,
+        0,
+        PaymentIdentifier::CustomId(unique_string()),
+        None,
+        1000.into(),
+        0.into(),
+        cashu::PaymentMethod::Bolt11,
+        0,
+        vec![],
+        vec![],
+    );
+
+    // Add quote
+    let mut tx = Database::begin_transaction(&db).await.unwrap();
+    tx.add_mint_quote(mint_quote.clone()).await.unwrap();
+    tx.commit().await.unwrap();
+
+    // First payment with payment_id "payment_1"
+    let mut tx = Database::begin_transaction(&db).await.unwrap();
+    let new_total = tx
+        .increment_mint_quote_amount_paid(&mint_quote.id, 300.into(), "payment_1".to_string())
+        .await
+        .unwrap();
+    assert_eq!(new_total, 300.into());
+    tx.commit().await.unwrap();
+
+    // Try to add the same payment_id again - should fail with Duplicate error
+    let mut tx = Database::begin_transaction(&db).await.unwrap();
+    let result = tx
+        .increment_mint_quote_amount_paid(&mint_quote.id, 300.into(), "payment_1".to_string())
+        .await;
+
+    assert!(
+        matches!(result.unwrap_err(), Error::Duplicate),
+        "Duplicate payment_id should be rejected"
+    );
+    tx.rollback().await.unwrap();
+
+    // Verify that the amount_paid is still 300 (not 600)
+    let retrieved = db.get_mint_quote(&mint_quote.id).await.unwrap().unwrap();
+    assert_eq!(retrieved.amount_paid(), 300.into());
+
+    // A different payment_id should succeed
+    let mut tx = Database::begin_transaction(&db).await.unwrap();
+    let new_total = tx
+        .increment_mint_quote_amount_paid(&mint_quote.id, 200.into(), "payment_2".to_string())
+        .await
+        .unwrap();
+    assert_eq!(new_total, 500.into());
+    tx.commit().await.unwrap();
+
+    // Verify final state
+    let retrieved = db.get_mint_quote(&mint_quote.id).await.unwrap().unwrap();
+    assert_eq!(retrieved.amount_paid(), 500.into());
+}

+ 2 - 1
crates/cdk-common/src/database/mint/test/mod.rs

@@ -301,7 +301,8 @@ macro_rules! mint_db_test {
             get_melt_quote_in_transaction,
             get_mint_quote_by_request_in_transaction,
             get_mint_quote_by_request_lookup_id_in_transaction,
-            get_blind_signatures_in_transaction
+            get_blind_signatures_in_transaction,
+            reject_duplicate_payment_ids
         );
     };
     ($make_db_fn:ident, $($name:ident),+ $(,)?) => {