Skip to content

Commit e7438b5

Browse files
committed
add tests
1 parent 9631992 commit e7438b5

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

src/Nethermind/Nethermind.Network.Test/MessageDictionaryTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ public void Test_Send_MessageDisposing_OnInvalidId()
105105
response.Received().Dispose();
106106
}
107107

108+
[Test]
109+
public void Test_Send_MessageDisposing_OnOldRequest()
110+
{
111+
Request<Eth66Message<GetBlockHeadersMessage>, IOwnedReadOnlyList<BlockHeader>> request = CreateRequest(111);
112+
113+
_testMessageDictionary.Send(request);
114+
115+
// Simulate a request timed out
116+
request.CompletionSource.TrySetException(new TimeoutException());
117+
118+
IOwnedReadOnlyList<BlockHeader> response = Substitute.For<IOwnedReadOnlyList<BlockHeader>>();
119+
_testMessageDictionary.Handle(111, response, 100);
120+
121+
response.Received().Dispose();
122+
}
123+
108124
[Test]
109125
public void Handle_disposes_tuple_disposable_component_on_unmatched_request()
110126
{

src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/Eth62ProtocolHandlerTests.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Nethermind.Consensus;
1313
using Nethermind.Consensus.Scheduler;
1414
using Nethermind.Core;
15+
using Nethermind.Core.Collections;
1516
using Nethermind.Core.Crypto;
1617
using Nethermind.Core.Extensions;
1718
using Nethermind.Core.Test;
@@ -565,6 +566,87 @@ public void Will_Not_Reschedule_SubmitTx_When_Queue_Is_Full()
565566
Assert.That(taskScheduler.ScheduledTasks, Is.EqualTo(1));
566567
}
567568

569+
[Test]
570+
public void Cancelled_mid_processing_releases_transactions_unless_rescheduled([Values] bool rescheduleSucceeds)
571+
{
572+
Transaction[] txs = new Transaction[2];
573+
for (int i = 0; i < txs.Length; i++)
574+
{
575+
txs[i] = Build.A.Transaction.SignedAndResolved().TestObject;
576+
txs[i].SetPreHashNoLock([(byte)(i + 1)]);
577+
}
578+
579+
ArrayPoolList<Transaction> list = new(txs.Length, txs);
580+
581+
using CancellationTokenSource cts = new();
582+
bool triedToReschedule = false;
583+
584+
// process first transaction and reschedule
585+
_transactionPool.SubmitTx(Arg.Any<Transaction>(), TxHandlingOptions.None).Returns(ctx =>
586+
{
587+
Transaction tx = ctx.Arg<Transaction>();
588+
_ = tx.Hash;
589+
cts.Cancel();
590+
return AcceptTxResult.Accepted;
591+
});
592+
593+
CallbackBackgroundTaskScheduler scheduler = new(() =>
594+
{
595+
triedToReschedule = true;
596+
if (rescheduleSucceeds)
597+
{
598+
// The new task now owns the remaining txs: process tx[1] and release the list.
599+
list[1].ClearPreHash();
600+
list.Dispose();
601+
}
602+
return rescheduleSucceeds;
603+
});
604+
605+
606+
using TestEth62ProtocolHandler handler = new(
607+
_session,
608+
_svc,
609+
new NodeStatsManager(Substitute.For<ITimerFactory>(), LimboLogs.Instance),
610+
_syncManager,
611+
scheduler,
612+
_transactionPool,
613+
_gossipPolicy,
614+
LimboLogs.Instance,
615+
_txGossipPolicy);
616+
617+
handler.HandleSlowPublic(list, cts.Token);
618+
619+
using (Assert.EnterMultipleScope())
620+
{
621+
Assert.That(triedToReschedule, Is.True);
622+
Assert.That(txs[0].Hash, Is.Not.Null);
623+
Assert.That(txs[1].Hash, Is.Null);
624+
Assert.Throws<ObjectDisposedException>(() => _ = list[0]);
625+
}
626+
}
627+
628+
private sealed class TestEth62ProtocolHandler(
629+
ISession session,
630+
IMessageSerializationService serializer,
631+
INodeStatsManager statsManager,
632+
ISyncServer syncServer,
633+
IBackgroundTaskScheduler backgroundTaskScheduler,
634+
ITxPool txPool,
635+
IGossipPolicy gossipPolicy,
636+
ILogManager logManager,
637+
ITxGossipPolicy? transactionsGossipPolicy = null)
638+
: Eth62ProtocolHandler(session, serializer, statsManager, syncServer, backgroundTaskScheduler, txPool, gossipPolicy, logManager, transactionsGossipPolicy)
639+
{
640+
public void HandleSlowPublic(IOwnedReadOnlyList<Transaction> transactions, CancellationToken cancellationToken) =>
641+
HandleSlow(new TransactionsRequest(transactions, 0), cancellationToken).GetAwaiter().GetResult();
642+
}
643+
644+
private sealed class CallbackBackgroundTaskScheduler(Func<bool> onSchedule) : IBackgroundTaskScheduler
645+
{
646+
public bool TryScheduleTask<TReq>(TReq request, Func<TReq, CancellationToken, Task> fulfillFunc,
647+
TimeSpan? timeout = null, string? source = null) => onSchedule();
648+
}
649+
568650
[Test]
569651
public void Can_handle_transactions_without_filtering()
570652
{

0 commit comments

Comments
 (0)