ledger.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. use cucumber::{given, then, when, World};
  2. use std::sync::Arc;
  3. use verax::{storage::SQLite, Asset};
  4. #[derive(Debug, World)]
  5. pub struct LedgerWorld {
  6. ledger: Arc<verax::Ledger<SQLite>>,
  7. revisions: Vec<verax::RevId>,
  8. }
  9. impl Default for LedgerWorld {
  10. fn default() -> Self {
  11. futures::executor::block_on(async move {
  12. let settings = "sqlite://:memory:"
  13. .parse::<verax::storage::sqlite::SqliteConnectOptions>()
  14. .expect("valid settings")
  15. .journal_mode(verax::storage::sqlite::SqliteJournalMode::Wal)
  16. .create_if_missing(true);
  17. let pool = verax::storage::sqlite::SqlitePoolOptions::new()
  18. .connect_with(settings)
  19. .await
  20. .expect("pool");
  21. let db = SQLite::new(pool);
  22. db.setup().await.expect("setup");
  23. Self {
  24. ledger: verax::Ledger::new(db.into()),
  25. revisions: vec![],
  26. }
  27. })
  28. }
  29. }
  30. #[given(expr = "a {word} deposit of {word} {word} for {word}")]
  31. async fn deposit_funds(
  32. world: &mut LedgerWorld,
  33. status: String,
  34. amount: String,
  35. asset: String,
  36. account: String,
  37. ) {
  38. let asset = asset.parse::<Asset>().expect("valid asset");
  39. world.revisions.push(
  40. world
  41. .ledger
  42. .deposit(
  43. &account.parse().expect("valid account"),
  44. asset.from_human(&amount).expect("valid amount"),
  45. status.parse().expect("valid status"),
  46. vec![],
  47. "Initial deposit".to_owned(),
  48. )
  49. .await
  50. .expect("deposit")
  51. .revision_id,
  52. );
  53. }
  54. #[when(expr = "update last transaction set status to {word}")]
  55. async fn update_status_from_last_tx(world: &mut LedgerWorld, new_status: String) {
  56. let revision = world.revisions.pop().expect("has last revision");
  57. let status = new_status.parse().expect("valid status");
  58. world.revisions.push(
  59. world
  60. .ledger
  61. .change_status(revision, status, "update status".to_owned())
  62. .await
  63. .expect("update status")
  64. .revision_id,
  65. );
  66. }
  67. #[then(expr = "{word} has no balance")]
  68. async fn check_balance_empty(world: &mut LedgerWorld, account: String) {
  69. let balance = world
  70. .ledger
  71. .get_balance(&account.parse().expect("valid account"))
  72. .await
  73. .expect("balance")
  74. .into_iter()
  75. .filter(|b| b.cents() != 0)
  76. .collect::<Vec<_>>();
  77. assert_eq!(0, balance.len())
  78. }
  79. #[then(expr = "{word} has balance of {word} {word}")]
  80. async fn check_balance(world: &mut LedgerWorld, account: String, amount: String, asset: String) {
  81. let asset = asset.parse::<Asset>().expect("valid asset");
  82. let amount = asset.from_human(&amount).expect("valid amount");
  83. let balances = world
  84. .ledger
  85. .get_balance(&account.parse().expect("valid account"))
  86. .await
  87. .expect("balance")
  88. .into_iter()
  89. .filter(|b| b.asset() == &asset)
  90. .collect::<Vec<_>>();
  91. assert_eq!(1, balances.len(), "{} is found", asset);
  92. assert_eq!(balances.get(0), Some(&amount));
  93. }
  94. #[tokio::main]
  95. async fn main() {
  96. LedgerWorld::run("tests/simple.feature").await;
  97. }