#include #include "csp/db/sqlite_db.h" #include "csp/services/auth_service.h" #include "csp/services/source_crystal_service.h" namespace { double AbsDiff(double a, double b) { const double d = a - b; return d < 0 ? -d : d; } } // namespace TEST_CASE("source crystal deposit withdraw interest and settings") { auto db = csp::db::SqliteDb::OpenMemory(); csp::db::ApplyMigrations(db); csp::db::SeedDemoData(db); csp::services::AuthService auth(db); const auto user = auth.Register("crystal_user", "password123"); csp::services::SourceCrystalService crystal(db); const auto s0 = crystal.GetSummary(user.user_id); REQUIRE(s0.user_id == user.user_id); REQUIRE(AbsDiff(s0.balance, 0.0) < 1e-9); REQUIRE(s0.monthly_interest_rate >= 0.0); const auto d1 = crystal.Deposit(user.user_id, 100.0, "initial deposit"); REQUIRE(d1.tx_type == "deposit"); REQUIRE(AbsDiff(d1.amount, 100.0) < 1e-9); REQUIRE(d1.balance_after > 99.99); const auto w1 = crystal.Withdraw(user.user_id, 30.0, "buy resources"); REQUIRE(w1.tx_type == "withdraw"); REQUIRE(AbsDiff(w1.amount, -30.0) < 1e-9); REQUIRE(w1.balance_after > 69.99); REQUIRE(w1.balance_after < 70.01); db.Exec("UPDATE source_crystal_accounts " "SET last_interest_at = last_interest_at - 7776000 " "WHERE user_id=" + std::to_string(user.user_id)); db.Exec("UPDATE source_crystal_transactions " "SET created_at = created_at - 7776000 " "WHERE user_id=" + std::to_string(user.user_id)); const auto s1 = crystal.GetSummary(user.user_id); REQUIRE(s1.balance > 72.0); REQUIRE(s1.balance < 75.0); const auto records = crystal.ListTransactions(user.user_id, 50); REQUIRE(records.size() >= 3); const auto cfg = crystal.UpdateMonthlyInterestRate(0.05); REQUIRE(AbsDiff(cfg.monthly_interest_rate, 0.05) < 1e-9); const auto cfg2 = crystal.GetSettings(); REQUIRE(AbsDiff(cfg2.monthly_interest_rate, 0.05) < 1e-9); }