/* * This file is part of the Flowee project * Copyright (C) 2025 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "TestPayment.h" #include #include #include #include #include #include #include #include std::unique_ptr TestPayment::createWallet() { if (m_dir.isEmpty()) { QString basedir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); m_dir = basedir + QString("/floweepay-%1/").arg(QCoreApplication::instance()->applicationPid()); } std::unique_ptr wallet(Wallet::createWallet(m_dir.toStdString(), 1111, "test")); return wallet; } void TestPayment::basic() { Streaming::ConstBuffer saveFile; { Payment payment; payment.setPaymentAmount(1001000); payment.setUserComment("my comment"); QCOMPARE(payment.paymentAmount(), 1001000); payment.setFeePerByte(80); payment.setFiatPrice(40000); // price per coin. QCOMPARE(payment.feePerByte(), 80); QCOMPARE(payment.paymentAmount(), 1001000); QCOMPARE(payment.paymentAmountFiat(), 400); QCOMPARE(payment.userComment(), "my comment"); auto pool = std::make_shared(); saveFile = payment.save(pool); } auto dummy = createWallet(); { Payment payment(saveFile, dummy.get()); QCOMPARE(payment.feePerByte(), 80); QCOMPARE(payment.paymentAmount(), 1001000); QCOMPARE(payment.paymentAmountFiat(), 400); QCOMPARE(payment.userComment(), "my comment"); } } void TestPayment::saveOutput() { auto pool = std::make_shared(); Streaming::ConstBuffer saveFile; { Payment payment; payment.setFiatPrice(40000); // price per coin. auto det = payment.paymentDetails(); QCOMPARE(det.size() , 1); auto *out = qobject_cast(det.at(0)); QVERIFY(out != nullptr); out->setPaymentAmount(999011124); out->setFiatFollows(true); out->setAddress("hello"); saveFile = payment.save(pool); } auto dummy = createWallet(); { Payment payment(saveFile, dummy.get()); auto det = payment.paymentDetails(); QCOMPARE(det.size() , 1); auto *out = qobject_cast(det.at(0)); QVERIFY(out != nullptr); QCOMPARE(out->paymentAmount(), 999011124); QCOMPARE(out->fiatFollows(), true); QVERIFY(out->outputScript().isEmpty()); QCOMPARE(out->address(), "hello"); QCOMPARE(payment.repeatDetails(), nullptr); const auto copy = out->paymentAmountFiat(); out->setFiatFollows(false); out->setPaymentAmountFiat(copy); saveFile = payment.save(pool); } pool->write("someScript"); Streaming::ConstBuffer outScript = pool->commit(); QCOMPARE(outScript.size(), 10); { Payment payment(saveFile, dummy.get()); auto det = payment.paymentDetails(); QCOMPARE(det.size() , 1); auto *out = qobject_cast(det.at(0)); QVERIFY(out != nullptr); QCOMPARE(out->fiatFollows(), false); QCOMPARE(out->paymentAmount(), 999010000); // some rounding. QVERIFY(out->outputScript().isEmpty()); QCOMPARE(out->address(), "hello"); QCOMPARE(payment.repeatDetails(), nullptr); out->setOutputScript(outScript); QVERIFY(out->address().isEmpty()); saveFile = payment.save(pool); } { Payment payment(saveFile, dummy.get()); auto det = payment.paymentDetails(); QCOMPARE(det.size() , 1); auto *out = qobject_cast(det.at(0)); QVERIFY(out != nullptr); QCOMPARE(out->fiatFollows(), false); QCOMPARE(out->paymentAmount(), 999010000); QCOMPARE(out->outputScript(), outScript); QVERIFY(out->address().isEmpty()); QCOMPARE(payment.repeatDetails(), nullptr); } } void TestPayment::saveRepeat() { auto pool = std::make_shared(); Streaming::ConstBuffer saveFile; { Payment payment; payment.setFiatPrice(40000); // price per coin. QCOMPARE(payment.repeatDetails(), nullptr); payment.makeRepeating(); auto *r = payment.repeatDetails(); QVERIFY(r != nullptr); // first an empty one. saveFile = payment.save(pool); } auto dummy = createWallet(); { Payment payment; QCOMPARE(payment.repeatDetails(), nullptr); payment.makeRepeating(); auto *r = payment.repeatDetails(); QVERIFY(r != nullptr); r->addRepeatDayOfMonth(30, 1, 4); r->addRepeatDayOfMonth(7); r->addRepeatDayOfMonth(9, 2); saveFile = payment.save(pool); } { Payment payment(saveFile, dummy.get()); auto *r = payment.repeatDetails(); QVERIFY(r != nullptr); QVERIFY(!r->sunset().isValid()); auto confs = r->repeatConfig(); QCOMPARE(confs.size(), 3); auto conf = confs.at(0); // they get sorted on insert. QCOMPARE(conf.dayOfMonth, 7); QCOMPARE(conf.dayOfWeek, -1); QCOMPARE(conf.weekInterval, -1); QCOMPARE(conf.monthInterval, -1); conf = confs.at(1); QCOMPARE(conf.dayOfMonth, 9); QCOMPARE(conf.dayOfWeek, -1); QCOMPARE(conf.weekInterval, 2); QCOMPARE(conf.monthInterval, -1); conf = confs.at(2); QCOMPARE(conf.dayOfMonth, 30); QCOMPARE(conf.dayOfWeek, -1); QCOMPARE(conf.weekInterval, 1); QCOMPARE(conf.monthInterval, 4); r->setRepeatConfig(QVector()); // clear r->addRepeatRelative(1, 4); r->setSunset(QDate(2030, 10, 30)); confs = r->repeatConfig(); confs[0].baseDate = QDateTime(QDate(2025, 05, 3), QTime(14,00)); r->setRepeatConfig(confs); QCOMPARE(r->currencyLocale(), ""); QCOMPARE(r->enabled(), true); QCOMPARE(r->autoApprove(), false); r->setCurrencyLocale("en_FL"); r->setEnabled(false); r->setAutoApprove(true); saveFile = payment.save(pool); } { Payment payment(saveFile, dummy.get()); auto *r = payment.repeatDetails(); QVERIFY(r != nullptr); QCOMPARE(r->sunset(), QDate(2030, 10, 30)); auto confs = r->repeatConfig(); QCOMPARE(confs.size(), 1); auto conf = confs.at(0); QCOMPARE(conf.dayOfMonth, -1); QCOMPARE(conf.dayOfWeek, 1); QCOMPARE(conf.weekInterval, 4); QCOMPARE(conf.monthInterval, -1); QCOMPARE(conf.baseDate, QDateTime(QDate(2025, 05, 3), QTime(14,00))); QCOMPARE(r->currencyLocale(), "en_FL"); QCOMPARE(r->enabled(), false); QCOMPARE(r->autoApprove(), true); // saveFile = payment.save(pool); } } void TestPayment::next() { const QTime time(13, 34); RepeatPaymentDetails::Config config; config.dayOfMonth = 13; config.baseDate = QDateTime(QDate(2025, 3, 20), time); QCOMPARE(config.next(), QDateTime(QDate(2025, 4, 13), time)); config.monthInterval = 3; QCOMPARE(config.next(), QDateTime(QDate(2025, 6, 13), time)); config.monthInterval = -1; QCOMPARE(config.next(), QDateTime(QDate(2025, 4, 13), time)); config.baseDate = QDateTime(QDate(2025, 1, 30), time); QCOMPARE(config.next(), QDateTime(QDate(2025, 2, 13), time)); config.baseDate = QDateTime(QDate(2025, 2, 13), time); QCOMPARE(config.next(), QDateTime(QDate(2025, 3, 13), time)); config.monthInterval = 3; QCOMPARE(config.next(), QDateTime(QDate(2025, 5, 13), time)); // impossible date handling config.baseDate = QDateTime(QDate(2025, 2, 4), time); config.dayOfMonth = 31; config.monthInterval = 3; // As feb 31 is impossible, I expect it to be May due to the 3 month interval QCOMPARE(config.next(), QDateTime(QDate(2025, 5, 31), time)); config.monthInterval = 12; // an impossible repeat QVERIFY(!config.next().isValid()); config = RepeatPaymentDetails::Config(); config.dayOfWeek = 2; // tuesday config.baseDate = QDateTime(QDate(2025, 3, 20), time); QCOMPARE(config.next(), QDateTime(QDate(2025, 3, 25), time)); config.baseDate = QDateTime(QDate(2025, 3, 25), time); QCOMPARE(config.next(), QDateTime(QDate(2025, 4, 1), time)); config.weekInterval = 2; QCOMPARE(config.next(), QDateTime(QDate(2025, 4, 8), time)); config.weekInterval = 3; QCOMPARE(config.next(), QDateTime(QDate(2025, 4, 15), time)); config.weekInterval = 7; QCOMPARE(config.next(), QDateTime(QDate(2025, 5, 13), time)); config.weekInterval = 0; config.monthInterval = 2; QCOMPARE(config.next(), QDateTime(QDate(2025, 5, 27), time)); } QTEST_MAIN(TestPayment)