Skip to content

Commit 3584458

Browse files
Reset tests implementation for TestMoneroWalletCommon
This commit includes also fixes for MoneroTxConfig
1 parent 713bc5c commit 3584458

3 files changed

Lines changed: 354 additions & 46 deletions

File tree

Monero.Test/TestMoneroWalletCommon.cs

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3019,6 +3019,314 @@ public void TestSaveAndClose()
30193019

30203020
#region Reset Tests
30213021

3022+
// Can sweep subaddresses
3023+
[Fact]
3024+
public void TestSweepSubaddresses()
3025+
{
3026+
Assert.True(TEST_RESETS);
3027+
TestUtils.WALLET_TX_TRACKER.WaitForWalletTxsToClearPool(wallet);
3028+
3029+
const int NUM_SUBADDRESSES_TO_SWEEP = 2;
3030+
3031+
// collect subaddresses with balance and unlocked balance
3032+
List<MoneroSubaddress> subaddresses = new List<MoneroSubaddress>();
3033+
List<MoneroSubaddress> subaddressesBalance = new List<MoneroSubaddress>();
3034+
List<MoneroSubaddress> subaddressesUnlocked = new List<MoneroSubaddress>();
3035+
foreach (MoneroAccount account in wallet.GetAccounts(true))
3036+
{
3037+
if (account.GetIndex() == 0) continue; // skip default account
3038+
foreach (MoneroSubaddress subaddress in account.GetSubaddresses())
3039+
{
3040+
subaddresses.Add(subaddress);
3041+
if (((ulong)subaddress.GetBalance()).CompareTo(TestUtils.MAX_FEE) > 0) subaddressesBalance.Add(subaddress);
3042+
if (((ulong)subaddress.GetUnlockedBalance()).CompareTo(TestUtils.MAX_FEE) > 0) subaddressesUnlocked.Add(subaddress);
3043+
}
3044+
}
3045+
3046+
// test requires at least one more subaddresses than the number being swept to verify it does not change
3047+
Assert.True(subaddressesBalance.Count >= NUM_SUBADDRESSES_TO_SWEEP + 1, "Test requires balance in at least " + (NUM_SUBADDRESSES_TO_SWEEP + 1) + " subaddresses from non-default acccount; run send-to-multiple tests");
3048+
Assert.True(subaddressesUnlocked.Count >= NUM_SUBADDRESSES_TO_SWEEP + 1, "Wallet is waiting on unlocked funds");
3049+
3050+
// sweep from first unlocked subaddresses
3051+
for (int i = 0; i < NUM_SUBADDRESSES_TO_SWEEP; i++)
3052+
{
3053+
3054+
// sweep unlocked account
3055+
MoneroSubaddress unlockedSubaddress = subaddressesUnlocked[i];
3056+
MoneroTxConfig config = new MoneroTxConfig()
3057+
.SetAddress(wallet.GetPrimaryAddress())
3058+
.SetAccountIndex(unlockedSubaddress.GetAccountIndex())
3059+
.SetSubaddressIndices([(uint)unlockedSubaddress.GetIndex()])
3060+
.SetRelay(true);
3061+
List<MoneroTxWallet> txs = wallet.SweepUnlocked(config);
3062+
3063+
// test transactions
3064+
Assert.True(txs.Count > 0);
3065+
foreach (MoneroTxWallet tx in txs)
3066+
{
3067+
Assert.True(tx.GetTxSet().GetTxs().Contains(tx));
3068+
TxContext ctx = new TxContext();
3069+
ctx.Wallet = wallet;
3070+
ctx.Config = config;
3071+
ctx.IsSendResponse = true;
3072+
ctx.IsSweepResponse = true;
3073+
TestTxWallet(tx, ctx);
3074+
}
3075+
3076+
// Assert. unlocked balance is less than max fee
3077+
MoneroSubaddress subaddress = wallet.GetSubaddress(((uint)unlockedSubaddress.GetAccountIndex()), ((uint)unlockedSubaddress.GetIndex()));
3078+
Assert.True(((ulong)subaddress.GetUnlockedBalance()).CompareTo(TestUtils.MAX_FEE) < 0);
3079+
}
3080+
3081+
// test subaddresses after sweeping
3082+
List<MoneroSubaddress> subaddressesAfter = new List<MoneroSubaddress>();
3083+
foreach (MoneroAccount account in wallet.GetAccounts(true))
3084+
{
3085+
if (account.GetIndex() == 0) continue; // skip default account
3086+
foreach (MoneroSubaddress subaddress in account.GetSubaddresses())
3087+
{
3088+
subaddressesAfter.Add(subaddress);
3089+
}
3090+
}
3091+
Assert.Equal(subaddresses.Count, subaddressesAfter.Count);
3092+
for (int i = 0; i < subaddresses.Count; i++)
3093+
{
3094+
MoneroSubaddress subaddressBefore = subaddresses[i];
3095+
MoneroSubaddress subaddressAfter = subaddressesAfter[i];
3096+
3097+
// determine if subaddress was swept
3098+
bool swept = false;
3099+
for (int j = 0; j < NUM_SUBADDRESSES_TO_SWEEP; j++)
3100+
{
3101+
if (subaddressesUnlocked[j].GetAccountIndex().Equals(subaddressBefore.GetAccountIndex()) && subaddressesUnlocked[j].GetIndex().Equals(subaddressBefore.GetIndex()))
3102+
{
3103+
swept = true;
3104+
break;
3105+
}
3106+
}
3107+
3108+
// Assert. unlocked balance is less than max fee if swept, unchanged otherwise
3109+
if (swept)
3110+
{
3111+
Assert.True(((ulong)subaddressAfter.GetUnlockedBalance()).CompareTo(TestUtils.MAX_FEE) < 0);
3112+
}
3113+
else
3114+
{
3115+
Assert.True(((ulong)subaddressBefore.GetUnlockedBalance()).CompareTo(subaddressAfter.GetUnlockedBalance()) == 0);
3116+
}
3117+
}
3118+
}
3119+
3120+
// Can sweep accounts
3121+
[Fact]
3122+
public void TestSweepAccounts()
3123+
{
3124+
Assert.True(TEST_RESETS);
3125+
TestUtils.WALLET_TX_TRACKER.WaitForWalletTxsToClearPool(wallet);
3126+
3127+
const int NUM_ACCOUNTS_TO_SWEEP = 1;
3128+
3129+
// collect accounts with sufficient balance and unlocked balance to cover the fee
3130+
List<MoneroAccount> accounts = wallet.GetAccounts(true);
3131+
List<MoneroAccount> accountsBalance = new List<MoneroAccount>();
3132+
List<MoneroAccount> accountsUnlocked = new List<MoneroAccount>();
3133+
foreach (MoneroAccount account in accounts)
3134+
{
3135+
if (account.GetIndex() == 0) continue; // skip default account
3136+
if (account.GetBalance().CompareTo(TestUtils.MAX_FEE) > 0) accountsBalance.Add(account);
3137+
if (account.GetUnlockedBalance().CompareTo(TestUtils.MAX_FEE) > 0) accountsUnlocked.Add(account);
3138+
}
3139+
3140+
// test requires at least one more accounts than the number being swept to verify it does not change
3141+
Assert.True(accountsBalance.Count >= NUM_ACCOUNTS_TO_SWEEP + 1, "Test requires balance greater than the fee in at least " + (NUM_ACCOUNTS_TO_SWEEP + 1) + " non-default accounts; run send-to-multiple tests");
3142+
Assert.True(accountsUnlocked.Count >= NUM_ACCOUNTS_TO_SWEEP + 1, "Wallet is waiting on unlocked funds");
3143+
3144+
// sweep from first unlocked accounts
3145+
for (int i = 0; i < NUM_ACCOUNTS_TO_SWEEP; i++)
3146+
{
3147+
3148+
// sweep unlocked account
3149+
MoneroAccount unlockedAccount = accountsUnlocked[i];
3150+
MoneroTxConfig config = new MoneroTxConfig().SetAddress(wallet.GetPrimaryAddress()).SetAccountIndex(unlockedAccount.GetIndex()).SetRelay(true);
3151+
List<MoneroTxWallet> txs = wallet.SweepUnlocked(config);
3152+
3153+
// test transactions
3154+
Assert.True(txs.Count > 0);
3155+
foreach (MoneroTxWallet tx in txs)
3156+
{
3157+
TxContext ctx = new TxContext();
3158+
ctx.Wallet = wallet;
3159+
ctx.Config = config;
3160+
ctx.IsSendResponse = true;
3161+
ctx.IsSweepResponse = true;
3162+
TestTxWallet(tx, ctx);
3163+
Assert.NotNull(tx.GetTxSet());
3164+
Assert.True(tx.GetTxSet().GetTxs().Contains(tx));
3165+
}
3166+
3167+
// Assert. unlocked account balance less than max fee
3168+
MoneroAccount account = wallet.GetAccount((uint)unlockedAccount.GetIndex());
3169+
Assert.True(account.GetUnlockedBalance().CompareTo(TestUtils.MAX_FEE) < 0);
3170+
}
3171+
3172+
// test accounts after sweeping
3173+
List<MoneroAccount> accountsAfter = wallet.GetAccounts(true);
3174+
Assert.Equal(accounts.Count, accountsAfter.Count);
3175+
for (int i = 0; i < accounts.Count; i++)
3176+
{
3177+
MoneroAccount accountBefore = accounts[i];
3178+
MoneroAccount accountAfter = accountsAfter[i];
3179+
3180+
// determine if account was swept
3181+
bool swept = false;
3182+
for (int j = 0; j < NUM_ACCOUNTS_TO_SWEEP; j++)
3183+
{
3184+
if (accountsUnlocked[j].GetIndex().Equals(accountBefore.GetIndex()))
3185+
{
3186+
swept = true;
3187+
break;
3188+
}
3189+
}
3190+
3191+
// Assert. unlocked balance is less than max fee if swept, unchanged otherwise
3192+
if (swept)
3193+
{
3194+
Assert.True(accountAfter.GetUnlockedBalance().CompareTo(TestUtils.MAX_FEE) < 0);
3195+
}
3196+
else
3197+
{
3198+
Assert.True(accountBefore.GetUnlockedBalance().CompareTo(accountAfter.GetUnlockedBalance()) == 0);
3199+
}
3200+
}
3201+
}
3202+
3203+
// Can sweep the whole wallet by accounts
3204+
[Fact(Skip = "Disabled so tests don't sweep the whole wallet")]
3205+
public void TestSweepWalletByAccounts()
3206+
{
3207+
Assert.True(TEST_RESETS);
3208+
TestSweepWallet(null);
3209+
}
3210+
3211+
// Can sweep the whole wallet by subaddresses
3212+
[Fact(Skip = "Disabled so tests don't sweep the whole wallet")]
3213+
public void TestSweepWalletBySubaddresses()
3214+
{
3215+
Assert.True(TEST_RESETS);
3216+
TestSweepWallet(true);
3217+
}
3218+
3219+
private void TestSweepWallet(bool? sweepEachSubaddress)
3220+
{
3221+
TestUtils.WALLET_TX_TRACKER.WaitForWalletTxsToClearPool(wallet);
3222+
3223+
// verify 2 subaddresses with enough unlocked balance to cover the fee
3224+
List<MoneroSubaddress> subaddressesBalance = new List<MoneroSubaddress>();
3225+
List<MoneroSubaddress> subaddressesUnlocked = new List<MoneroSubaddress>();
3226+
foreach (MoneroAccount account in wallet.GetAccounts(true))
3227+
{
3228+
foreach (MoneroSubaddress subaddress in account.GetSubaddresses())
3229+
{
3230+
if (((ulong)subaddress.GetBalance()).CompareTo(TestUtils.MAX_FEE) > 0) subaddressesBalance.Add(subaddress);
3231+
if (((ulong)subaddress.GetUnlockedBalance()).CompareTo(TestUtils.MAX_FEE) > 0) subaddressesUnlocked.Add(subaddress);
3232+
}
3233+
}
3234+
Assert.True(subaddressesBalance.Count >= 2, "Test requires multiple accounts with a balance greater than the fee; run send to multiple first");
3235+
Assert.True(subaddressesUnlocked.Count >= 2, "Wallet is waiting on unlocked funds");
3236+
3237+
// sweep
3238+
string destination = wallet.GetPrimaryAddress();
3239+
MoneroTxConfig config = new MoneroTxConfig().SetAddress(destination).SetSweepEachSubaddress(sweepEachSubaddress).SetRelay(true);
3240+
MoneroTxConfig copy = config.Clone();
3241+
List<MoneroTxWallet> txs = wallet.SweepUnlocked(config);
3242+
Assert.Equal(copy, config); // config is unchanged
3243+
foreach (MoneroTxWallet tx in txs)
3244+
{
3245+
Assert.True(tx.GetTxSet().GetTxs().Contains(tx));
3246+
Assert.Null(tx.GetTxSet().GetMultisigTxHex());
3247+
Assert.Null(tx.GetTxSet().GetSignedTxHex());
3248+
Assert.Null(tx.GetTxSet().GetUnsignedTxHex());
3249+
}
3250+
Assert.True(txs.Count > 0);
3251+
foreach (MoneroTxWallet tx in txs)
3252+
{
3253+
config = new MoneroTxConfig()
3254+
.SetAddress(destination)
3255+
.SetAccountIndex(tx.GetOutgoingTransfer().GetAccountIndex())
3256+
.SetSweepEachSubaddress(sweepEachSubaddress)
3257+
.SetRelay(true);
3258+
TxContext ctx = new TxContext();
3259+
ctx.Wallet = wallet;
3260+
ctx.Config = config;
3261+
ctx.IsSendResponse = true;
3262+
ctx.IsSweepResponse = true;
3263+
TestTxWallet(tx, ctx);
3264+
}
3265+
3266+
// all unspent, unlocked outputs must be less than fee
3267+
List<MoneroOutputWallet> spendableOutputs = wallet.GetOutputs(new MoneroOutputQuery().SetIsSpent(false).SetTxQuery(new MoneroTxQuery().SetIsLocked(false)));
3268+
foreach (MoneroOutputWallet spendableOutput in spendableOutputs)
3269+
{
3270+
Assert.True(((ulong)spendableOutput.GetAmount()).CompareTo(TestUtils.MAX_FEE) < 0, "Unspent output should have been swept\n" + spendableOutput.ToString());
3271+
}
3272+
3273+
// all subaddress unlocked balances must be less than fee
3274+
subaddressesBalance.Clear();
3275+
subaddressesUnlocked.Clear();
3276+
foreach (MoneroAccount account in wallet.GetAccounts(true))
3277+
{
3278+
foreach (MoneroSubaddress subaddress in account.GetSubaddresses())
3279+
{
3280+
Assert.True(((ulong)subaddress.GetUnlockedBalance()).CompareTo(TestUtils.MAX_FEE) < 0, "No subaddress should have more unlocked than the fee");
3281+
}
3282+
}
3283+
}
3284+
3285+
// Can scan transactions by id
3286+
[Fact]
3287+
public void TestScanTxs()
3288+
{
3289+
3290+
// get a few tx hashes
3291+
List<string> txHashes = [];
3292+
List<MoneroTxWallet> txs = wallet.GetTxs();
3293+
if (txs.Count < 3) Assert.Fail("Not enough txs to scan");
3294+
for (int i = 0; i < 3; i++) txHashes.Add(txs[i].GetHash());
3295+
3296+
// start wallet without scanning
3297+
MoneroWallet scanWallet = CreateWallet(new MoneroWalletConfig().SetSeed(wallet.GetSeed()).SetRestoreHeight(0));
3298+
scanWallet.StopSyncing(); // TODO: create wallet without daemon connection (offline does not reconnect, default connects to localhost, offline then online causes confirmed txs to disappear)
3299+
Assert.True(scanWallet.IsConnectedToDaemon());
3300+
3301+
// scan txs
3302+
scanWallet.ScanTxs(txHashes);
3303+
3304+
// TODO: scanning txs causes merge problems reconciling 0 fee, isMinerTx with test txs
3305+
3306+
// // txs are scanned
3307+
// Assert.Equal(txHashes.Count, scanWallet.GetTxs().Count);
3308+
// for (int i = 0; i < txHashes.Count; i++) {
3309+
// Assert.Equal(wallet.GetTx(txHashes[i]), scanWallet.GetTx(txHashes[i]));
3310+
// }
3311+
// List<MoneroTxWallet> scannedTxs = scanWallet.GetTxs(txHashes);
3312+
// Assert.Equal(txHashes.Count, scannedTxs.Count);
3313+
3314+
// close wallet
3315+
CloseWallet(scanWallet, false);
3316+
}
3317+
3318+
// Can rescan the blockchain
3319+
[Fact(Skip = "Disabled so tests don't delete local cache")]
3320+
public void TestRescanBlockchain()
3321+
{
3322+
Assert.True(TEST_RESETS);
3323+
wallet.RescanBlockchain();
3324+
foreach (MoneroTxWallet tx in wallet.GetTxs())
3325+
{
3326+
TestTxWallet(tx, null);
3327+
}
3328+
}
3329+
30223330
#endregion
30233331

30243332
#region Notification Tests

0 commit comments

Comments
 (0)