-
Notifications
You must be signed in to change notification settings - Fork 37.7k
wallet test: Add test for subtract fee from recipient behavior #22155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I'm happy to drop the last commit if it's not wanted. Main goal of this PR is to add test coverage, which is what the first two commits do. The code cleanup in the third commit could be done in another PR or replaced with a different approach. UPDATE: Final commit def672f is dropped for now to make the PR smaller and test-only |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
I don't agree with the behavior in the case where the dust change is more than fees, but since this doesn't change the current behavior, I guess it's fine.
Here is a test for that edge case:
diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index 8c7794eb47..41ee5f3ea0 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -26,6 +26,8 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
int change_pos = -1;
bilingual_str error;
CCoinControl coin_control;
+ coin_control.m_feerate.emplace(10000);
+ coin_control.fOverrideFeeRate = true;
FeeCalculation fee_calc;
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc));
BOOST_CHECK_EQUAL(tx->vout.size(), 1);
@@ -35,14 +37,26 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
// Check subtract from recipient transaction slightly less than coinbase
// amount also does not create change output and pays extra dust amount to
// recipient instead of miner
- const CAmount dust_amount = 123;
- const CAmount expected_fee = fee;
+ CAmount dust_amount = 123;
+ CAmount expected_fee = fee;
recipient.nAmount -= dust_amount;
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc));
BOOST_CHECK_EQUAL(tx->vout.size(), 1);
BOOST_CHECK_EQUAL(tx->vout[0].nValue, recipient.nAmount - fee + dust_amount);
BOOST_CHECK_EQUAL(fee, expected_fee);
tx.reset();
+
+ // The dust amount is greater than the fee paid for this transaction.
+ // The entire dust amount should end up as fees, rather than the excess fee paid to the recipients.
+ dust_amount = 1350;
+ expected_fee = dust_amount;
+ recipient.nAmount = 50 * COIN - dust_amount;
+ BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc));
+ BOOST_CHECK_EQUAL(tx->vout.size(), 1);
+ BOOST_CHECK_EQUAL(tx->vout[0].nValue, recipient.nAmount - fee + dust_amount);
+ BOOST_CHECK_EQUAL(fee, expected_fee);
+ BOOST_CHECK_LE(tx->vout[0].nValue, recipient.nAmount);
+ tx.reset();
}
BOOST_AUTO_TEST_SUITE_END()
src/wallet/test/spend_tests.cpp
Outdated
CAmount fee; | ||
int change_pos = -1; | ||
bilingual_str error; | ||
CCoinControl coin_control; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In e459d01 "wallet test: Add test for subtract fee from recipient behavior"
Since fee estimation is not available in tests, the feerate that is used by this test is 0, which makes it not particularly meaningful. But we can set a feerate in the CCoinControl
and force it to be used, e.g.
CCoinControl coin_control; | |
CCoinControl coin_control; | |
coin_control.m_feerate.emplace(10000); | |
coin_control.fOverrideFeeRate = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since fee estimation is not available in tests, the feerate that is used by this test is 0, which makes it not particularly meaningful. But we can set a feerate in the
CCoinControl
and force it to be used, e.g.
Thank you, great catch! I had assumed a nonzero minimum relay fee would be used. I think the tests still did cover relevant to_reduce == 0
and to_reduce < 0
cases, but having a nonzero fee is obviously more realistic.
4f7c483
to
972e87c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for review! I incorporated all your test suggestions and new cases with a few additional tweaks.
Updated 73bd26c -> 972e87c (pr/subfee.2
-> pr/subfee.3
, compare) with suggested test improvements
src/wallet/test/spend_tests.cpp
Outdated
CAmount fee; | ||
int change_pos = -1; | ||
bilingual_str error; | ||
CCoinControl coin_control; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since fee estimation is not available in tests, the feerate that is used by this test is 0, which makes it not particularly meaningful. But we can set a feerate in the
CCoinControl
and force it to be used, e.g.
Thank you, great catch! I had assumed a nonzero minimum relay fee would be used. I think the tests still did cover relevant to_reduce == 0
and to_reduce < 0
cases, but having a nonzero fee is obviously more realistic.
ACK 972e87c |
Rebased 972e87c -> 8f6113f ( |
Concept ACK, good to see test coverage here. |
Updated 8f6113f -> 6a50482 ( |
re-ACK 6a50482 |
No change in behavior. This just moves some code from the ListCoins test setup to a reusable util function, so it can be reused in a new test in the next commit.
Behavior might have recently changed in bitcoin#17331 (it is not clear) but not noticed because there is no test coverage. This adds test coverage for current subtract from recipient behavior without changing it. Co-authored-by: Andrew Chow <achow101-github@achow101.com>
Rebased 6a50482 -> 0cc10f8 ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 0cc10f8 verified the new test also passes without the last commit
a few minor edits while reviewing, feel free to pick/choose/ignore (not sure about some of the includes)
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 45a02f59a1..b3a8d18446 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -764,8 +764,7 @@ bool CWallet::CreateTransactionInternal(
// 1. The change output would be dust
// 2. The change is within the (almost) exact match window, i.e. it is less than or equal to the cost of the change output (cost_of_change)
CAmount change_amount = change_position->nValue;
- if (IsDust(*change_position, coin_selection_params.m_discard_feerate) || change_amount <= coin_selection_params.m_cost_of_change)
- {
+ if (IsDust(*change_position, coin_selection_params.m_discard_feerate) || change_amount <= coin_selection_params.m_cost_of_change) {
nChangePosInOut = -1;
change_amount = 0;
txNew.vout.erase(change_position);
diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index a202dd9146..66e7de4273 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -22,7 +22,7 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
// be uneconomical to add and spend the output), and make sure it pays the
// leftover input amount which would have been change to the recipient
// instead of the miner.
- auto check_tx = [&](CAmount leftover_input_amount) {
+ auto check_tx = [&wallet](CAmount leftover_input_amount) {
CRecipient recipient{GetScriptForRawPubKey({}), 50 * COIN - leftover_input_amount, true /* subtract fee */};
CTransactionRef tx;
CAmount fee;
@@ -41,7 +41,7 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
// Send full input amount to recipient, check that only nonzero fee is
// subtracted (to_reduce == fee).
- const CAmount fee = check_tx(0);
+ const CAmount fee{check_tx(0)};
// Send slightly less than full input amount to recipient, check leftover
// input amount is paid to recipient not the miner (to_reduce == fee - 123)
diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp
index 097abf9310..f156dbc71d 100644
--- a/src/wallet/test/util.cpp
+++ b/src/wallet/test/util.cpp
@@ -5,12 +5,16 @@
#include <wallet/test/util.h>
#include <chain.h>
+#include <interfaces/chain.h>
+#include <key.h>
#include <test/util/setup_common.h>
#include <wallet/wallet.h>
#include <wallet/walletdb.h>
#include <boost/test/unit_test.hpp>
+#include <memory>
+
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
{
auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockWalletDatabase());
diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h
index 288c111571..a9d7ef70f0 100644
--- a/src/wallet/test/util.h
+++ b/src/wallet/test/util.h
@@ -5,6 +5,13 @@
#ifndef BITCOIN_WALLET_TEST_UTIL_H
#define BITCOIN_WALLET_TEST_UTIL_H
+#include <chain.h>
+#include <interfaces/chain.h>
+#include <key.h>
+#include <test/util/setup_common.h>
+#include <wallet/wallet.h>
+#include <wallet/walletdb.h>
+
#include <memory>
class CChain;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 9e7f1f3ed7..75a08b6f74 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -20,8 +20,8 @@
#include <util/translation.h>
#include <validation.h>
#include <wallet/coincontrol.h>
-#include <wallet/test/wallet_test_fixture.h>
#include <wallet/test/util.h>
+#include <wallet/test/wallet_test_fixture.h>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
Updated 0cc10f8 -> def672f ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK def672f per git diff 0cc10f8 def672f
, retested after rebase to current master, reverified the added test is green before and after the last commit
src/wallet/spend.cpp
Outdated
} | ||
|
||
// Reduce output values for subtractFeeFromAmount | ||
if (coin_selection_params.m_subtract_fee_outputs) { | ||
CAmount to_reduce = fee_needed + change_amount - change_and_fee; | ||
CAmount to_reduce = nFeeRet + change_amount - change_and_fee; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def672f (feel free to ignore)
CAmount to_reduce = nFeeRet + change_amount - change_and_fee; | |
const CAmount to_reduce{nFeeRet + change_amount - change_and_fee}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed first two commits. Great to see more coverage for coin selection!
I'm not sure what was the reason to extract a part of the ListCoinsTestingSetup
fixture in a standalone method instead of just using the fixture itself. One can move ListCoinsTestingSetup
to wallet/test/wallet_test_fixture.*
that seems like a good fit and is included anyway.
FeeCalculation fee_calc; | ||
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc)); | ||
BOOST_CHECK_EQUAL(tx->vout.size(), 1); | ||
BOOST_CHECK_EQUAL(tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it always just 50 * COIN - fee
I believe it'd be slightly easier to understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Isn't it always just
50 * COIN - fee
I believe it'd be slightly easier to understand
This is surprising to me, and I'm not sure how the thinking goes. I think recipient.nAmount + leftover_input_amount - fee
captures the idea that when the subtract-from-recipient option is used, the recipient will receive the amount originally requested (recipient.nAmount
) plus any dust amount (leftover_input_amount
) that is too small to refund to the sender, minus the fee (fee
). I'm not sure what 50 * COIN - fee
communicates since it is involving the block reward which is a just a coincidental part of the test setup. It seems like this would be checking for the right result incidentally instead of explicitly, and it could also be more difficult to extend or maintain because it is repeating hardcoded setup values which aren't related to the behavior being verified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thinking is that the recipient always gets the whole UTXO - fee.
On the first look it seemed to me that the value received would be different since leftover_input_amount
is different for different invocations. It took me some time to figure out that the leftover_input_amount
variable cancels out.
I understand your thinking as well and I don't know which one is better.
|
||
#include <memory> | ||
|
||
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reasons to extract this from ListCoinsTestingSetup
instead of using the fixture directly?
It looks like currently fixtures are preferred method of sharing setup/teardown between unit tests. ListCoinsTestingSetup
already exists and does exactly what we need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Any reasons to extract this from
ListCoinsTestingSetup
instead of using the fixture directly?It looks like currently fixtures are preferred method of sharing setup/teardown between unit tests.
ListCoinsTestingSetup
already exists and does exactly what we need.
Fixtures are overused in general right now, causing tests to do unnecessary work, and they make setup code that could be reused in other contexts (benchmarks & fuzz tests, future test & simulation code) harder to understand and less reusable. The current hierarchy of test fixtures that inherit from each other is also confusing and inflexible.
The suggestion here also seems a little vague, because I'm not sure what form or members you'd want a generic fixture to have. ListCoinsTestingSetup has more functionality than the new test requires, and less functionality than new tests may require. Would the new fixture only support tests with one synced wallet, or with multiple wallets? Would it require all the wallets to be created before each test starts, or could the tests create the wallets as needed?
The simplicity a CreateSyncedWallet
util function not tied to a class hierarchy makes more sense to me than a test fixture that is more complicated with more usage restrictions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixtures are overused in general right now, causing tests to do unnecessary work, and they make setup code that could be reused in other contexts (benchmarks & fuzz tests, future test & simulation code) harder to understand and less reusable.
In this specific case the fixture doesn't cause unnecessary work.
CreateSyncedWallet
function is used in only two places now: 1) in ListCoinsTestingSetup
and 2) in the new test that uses TestChain100Setup
fixture anyway.
In general I agree that fixtures are harder to reuse in other contexts but without having a real use case I'm not sure that CreateSyncedWallet
will actually meet the requirements.
The current hierarchy of test fixtures that inherit from each other is also confusing and inflexible.
But you are using fixtures anyway right now. So why then split some part of the setup in fixture and some part in a standalone method. Using two separate mechanism to do the test setup is even more confusing.
Also there is value in maintaining uniformity in how the test setup is done.
Fixtures are already used extensively in the code base. There are 72 test suites that use fixtures vs 24 that don't. According to my spot check the ones that don't use fixtures also don't use standalone setup function as a way to reuse setup code between tests.
The suggestion here also seems a little vague, because I'm not sure what form or members you'd want a generic fixture to have. ListCoinsTestingSetup has more functionality than the new test requires, and less functionality than new tests may require. Would the new fixture only support tests with one synced wallet, or with multiple wallets? Would it require all the wallets to be created before each test starts, or could the tests create the wallets as needed?
My suggestion is to not introduce a second mechanism to do test setups and just reuse existing fixture (probably renaming it to SyncedWalletTestingSetup
) because it has exactly the right setup.
The new SubtractFee
test has the setup exactly equivalent to the setup of ListCoinsTestingSetup
. ListCoinsTestingSetup
has also AddTx
method which is used exactly one time and could easily be inlined or extracted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
My suggestion is to not introduce a second mechanism to do test setups and just reuse existing fixture (probably renaming it to
SyncedWalletTestingSetup
) because it has exactly the right setup.
Yes, I see what you're saying here. If you can use fixtures to help with test setup, and you can also use normal functions to also help with test setup, then setup code might be less discoverable, and someone who is trying to write a new test and only looking at the fixtures might miss a function that could be useful. I would not deny that this is a drawback. I just think there are some advantages on the other side. (Functions that don't maintain state can be easier to understand than fixtures that are stateful. Functions can be more flexible than fixtures and in this case let you create many synced wallets instead of one. Functions can be shared across frameworks including boost framework, qt test framework, fuzzing framework, benchmark framework, and other future frameworks, instead of limited to the boost framework. And this change adds a place for more functions to go and more fixture code to be detached even if is not moving right away)
@@ -170,6 +170,8 @@ endif | |||
|
|||
|
|||
BITCOIN_TEST_SUITE += \ | |||
wallet/test/util.cpp \ | |||
wallet/test/util.h \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not reuse wallet/test/wallet_test_fixture.*
?
It already contains WalletTestingSetup
that we use anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Why not reuse
wallet/test/wallet_test_fixture.*
?
Responded in detail about the fixtures below.
|
||
BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup) | ||
|
||
BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to override fixture declared for test suite. You can do
BOOST_FIXTURE_TEST_SUITE(spend_tests, TestChain100Setup)
BOOST_AUTO_TEST_CASE(SubtractFee)
or
BOOST_AUTO_TEST_SUITE(spend_tests)
BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
No need to override fixture declared for test suite. You can do [...]
I know you can do these things, but don't see what makes them better or meaningfully different. What I think is nice about the current approach is that it makes spend_tests setup consistent with wallet_tests setup, and more efficient by default because the wallet test fixture does less work than the chain100 fixture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better because it avoids unnecessary information. WalletTestingSetup
is never used in the test suite.
There is no point in setting TEST_SUITE fixture to WalletTestingSetup
when the only test case in the test suite overrides the fixture and uses TestChain100Setup
. It's just unused information in the test that could potentially confuse readers.
Same goes for wallet_tests
. Every test case there defines there own fixture explicitly and don't inherit it from the test suite. I have no idea why it's like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the motivation now and yes I agree. WalletTestingSetup can be overkill because even if you are testing wallet code, you are likely testing smaller functions and classes that don't need the full setup. It's nicer in general to use simpler fixtures for efficiency and easier comprehension, and would be good to see use of fixtures cleaned up and simplified in future PRs. Consistency between spend_tests and wallet_tests here may at least help with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed first two commits. Great to see more coverage for coin selection!
Thanks for review! I just dropped the third (last) commit to make this a test-only change and avoid discouraging an ACK. I'll make a PR from it later if it's still useful after other coin selection updates.
I'm not sure what was the reason to extract a part of the
ListCoinsTestingSetup
fixture in a standalone method instead of just using the fixture itself. One can moveListCoinsTestingSetup
towallet/test/wallet_test_fixture.*
that seems like a good fit and is included anyway.
Thanks, responded in detail about the fixtures below.
Updated def672f -> fe6dc76 (pr/subfee.7
-> pr/subfee.8
, compare) dropping the final commit, so the PR is easier to review and test-only
@@ -170,6 +170,8 @@ endif | |||
|
|||
|
|||
BITCOIN_TEST_SUITE += \ | |||
wallet/test/util.cpp \ | |||
wallet/test/util.h \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Why not reuse
wallet/test/wallet_test_fixture.*
?
Responded in detail about the fixtures below.
|
||
BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup) | ||
|
||
BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
No need to override fixture declared for test suite. You can do [...]
I know you can do these things, but don't see what makes them better or meaningfully different. What I think is nice about the current approach is that it makes spend_tests setup consistent with wallet_tests setup, and more efficient by default because the wallet test fixture does less work than the chain100 fixture.
FeeCalculation fee_calc; | ||
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc)); | ||
BOOST_CHECK_EQUAL(tx->vout.size(), 1); | ||
BOOST_CHECK_EQUAL(tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Isn't it always just
50 * COIN - fee
I believe it'd be slightly easier to understand
This is surprising to me, and I'm not sure how the thinking goes. I think recipient.nAmount + leftover_input_amount - fee
captures the idea that when the subtract-from-recipient option is used, the recipient will receive the amount originally requested (recipient.nAmount
) plus any dust amount (leftover_input_amount
) that is too small to refund to the sender, minus the fee (fee
). I'm not sure what 50 * COIN - fee
communicates since it is involving the block reward which is a just a coincidental part of the test setup. It seems like this would be checking for the right result incidentally instead of explicitly, and it could also be more difficult to extend or maintain because it is repeating hardcoded setup values which aren't related to the behavior being verified.
|
||
#include <memory> | ||
|
||
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #22155 (comment)
Any reasons to extract this from
ListCoinsTestingSetup
instead of using the fixture directly?It looks like currently fixtures are preferred method of sharing setup/teardown between unit tests.
ListCoinsTestingSetup
already exists and does exactly what we need.
Fixtures are overused in general right now, causing tests to do unnecessary work, and they make setup code that could be reused in other contexts (benchmarks & fuzz tests, future test & simulation code) harder to understand and less reusable. The current hierarchy of test fixtures that inherit from each other is also confusing and inflexible.
The suggestion here also seems a little vague, because I'm not sure what form or members you'd want a generic fixture to have. ListCoinsTestingSetup has more functionality than the new test requires, and less functionality than new tests may require. Would the new fixture only support tests with one synced wallet, or with multiple wallets? Would it require all the wallets to be created before each test starts, or could the tests create the wallets as needed?
The simplicity a CreateSyncedWallet
util function not tied to a class hierarchy makes more sense to me than a test fixture that is more complicated with more usage restrictions.
ACK fe6dc76 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fe6dc76
Could also test this for multiple subtract fee recipients?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK fe6dc76.
coin_control.fOverrideFeeRate = true; | ||
FeeCalculation fee_calc; | ||
BOOST_CHECK(wallet->CreateTransaction({recipient}, tx, fee, change_pos, error, coin_control, fee_calc)); | ||
BOOST_CHECK_EQUAL(tx->vout.size(), 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, also check change_pos == -1
.
😱 Apparently I missed a review club about this https://bitcoincore.reviews/22155. Sorry I missed but relieved it didn't find any terrible problems! |
Good suggestions for followup
|
This adds test coverage for wallet subtract from recipient behavior without changing it. Behavior seems to have changed recently in a minor way in #17331 without being noticed.