This is an automated email from the ASF dual-hosted git repository. tabish pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton-dotnet.git
The following commit(s) were added to refs/heads/main by this push: new bd1a0da PROTON-2731 Validate timeout value passed to Receive early bd1a0da is described below commit bd1a0da76ba86a2f2ae9c85f13b8d74e8ca9017e Author: Timothy Bish <tabish...@gmail.com> AuthorDate: Tue May 9 18:58:27 2023 -0400 PROTON-2731 Validate timeout value passed to Receive early Prevent the event loop handler from getting blocked by unexpected error from the task API delay feature. --- .../Client/Implementation/ClientReceiver.cs | 6 +++ .../Client/Implementation/ClientStreamReceiver.cs | 6 +++ .../Client/Implementation/ClientBaseTestFixture.cs | 2 +- .../Client/Implementation/ClientReceiverTest.cs | 47 +++++++++++++++++++++ .../Implementation/ClientStreamReceiverTest.cs | 49 +++++++++++++++++++++- 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/Proton.Client/Client/Implementation/ClientReceiver.cs b/src/Proton.Client/Client/Implementation/ClientReceiver.cs index 0b840a1..5b7beea 100644 --- a/src/Proton.Client/Client/Implementation/ClientReceiver.cs +++ b/src/Proton.Client/Client/Implementation/ClientReceiver.cs @@ -89,6 +89,12 @@ namespace Apache.Qpid.Proton.Client.Implementation { if (timeout != TimeSpan.MaxValue) { + if (timeout.TotalMilliseconds > uint.MaxValue) + { + receive.TrySetException(new ArgumentOutOfRangeException( + "Receive timeout must convert to a value less than UInt32.MaxValue Milliseconds")); + } + session.Schedule(() => { if (!receive.Task.IsCompleted) diff --git a/src/Proton.Client/Client/Implementation/ClientStreamReceiver.cs b/src/Proton.Client/Client/Implementation/ClientStreamReceiver.cs index 182a915..e099df5 100644 --- a/src/Proton.Client/Client/Implementation/ClientStreamReceiver.cs +++ b/src/Proton.Client/Client/Implementation/ClientStreamReceiver.cs @@ -100,6 +100,12 @@ namespace Apache.Qpid.Proton.Client.Implementation { if (timeout != TimeSpan.MaxValue) { + if (timeout.TotalMilliseconds > uint.MaxValue) + { + receive.TrySetException(new ArgumentOutOfRangeException( + "Receive timeout must convert to a value less than UInt32.MaxValue Milliseconds")); + } + session.Schedule(() => { if (!receive.Task.IsCompleted) diff --git a/test/Proton.Client.Tests/Client/Implementation/ClientBaseTestFixture.cs b/test/Proton.Client.Tests/Client/Implementation/ClientBaseTestFixture.cs index 92eb8c0..14d2bca 100644 --- a/test/Proton.Client.Tests/Client/Implementation/ClientBaseTestFixture.cs +++ b/test/Proton.Client.Tests/Client/Implementation/ClientBaseTestFixture.cs @@ -46,7 +46,7 @@ namespace Apache.Qpid.Proton.Client.Implementation NLog.Targets.Target logconsole = new NLog.Targets.ConsoleTarget("logconsole"); // Rules for mapping loggers to targets - //config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logconsole); + // config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logconsole); config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logfile); loggerFactory = LoggerFactory.Create(builder => diff --git a/test/Proton.Client.Tests/Client/Implementation/ClientReceiverTest.cs b/test/Proton.Client.Tests/Client/Implementation/ClientReceiverTest.cs index 3a52d6f..fdb21f0 100644 --- a/test/Proton.Client.Tests/Client/Implementation/ClientReceiverTest.cs +++ b/test/Proton.Client.Tests/Client/Implementation/ClientReceiverTest.cs @@ -3137,6 +3137,53 @@ namespace Apache.Qpid.Proton.Client.Implementation } } + [Test] + public void TestDeliveryReadWithLongTimeoutValue() + { + byte[] payload = CreateEncodedMessage(new AmqpValue("Hello World")); + + using (ProtonTestServer peer = new ProtonTestServer(loggerFactory)) + { + peer.ExpectSASLAnonymousConnect(); + peer.ExpectOpen().Respond(); + peer.ExpectBegin().Respond(); + peer.ExpectAttach().OfReceiver().Respond(); + peer.ExpectFlow().WithLinkCredit(10); + peer.RemoteTransfer().WithHandle(0) + .WithDeliveryId(0) + .WithDeliveryTag(new byte[] { 1 }) + .WithMore(false) + .WithSettled(true) + .WithMessageFormat(0) + .WithPayload(payload).AfterDelay(20).Queue(); + peer.Start(); + + string remoteAddress = peer.ServerAddress; + int remotePort = peer.ServerPort; + + logger.LogInformation("Test started, peer listening on: {0}:{1}", remoteAddress, remotePort); + + IClient container = IClient.Create(); + IConnection connection = container.Connect(remoteAddress, remotePort); + ISession session = connection.OpenSession(); + IReceiver receiver = session.OpenReceiver("test-queue"); + + Assert.Throws<ArgumentOutOfRangeException>(() => receiver.Receive(TimeSpan.FromDays(50))); + + IDelivery delivery = receiver.Receive(TimeSpan.FromDays(49)); + Assert.IsNotNull(delivery); + + peer.WaitForScriptToComplete(); + peer.ExpectDetach().Respond(); + peer.ExpectClose().Respond(); + + receiver.Close(); + connection.Close(); + + peer.WaitForScriptToComplete(); + } + } + private class AmqpJmsSelectorType : IDescribedType { private string selector; diff --git a/test/Proton.Client.Tests/Client/Implementation/ClientStreamReceiverTest.cs b/test/Proton.Client.Tests/Client/Implementation/ClientStreamReceiverTest.cs index e674829..ad0ce6b 100644 --- a/test/Proton.Client.Tests/Client/Implementation/ClientStreamReceiverTest.cs +++ b/test/Proton.Client.Tests/Client/Implementation/ClientStreamReceiverTest.cs @@ -4189,7 +4189,7 @@ namespace Apache.Qpid.Proton.Client.Implementation IClient container = IClient.Create(); IConnection connection = container.Connect(remoteAddress, remotePort); - IStreamReceiver receiver = (IStreamReceiver)connection.OpenStreamReceiver("test-queue").OpenTask.Result; + IStreamReceiver receiver = connection.OpenStreamReceiver("test-queue").OpenTask.Result; byte[] payload = CreateEncodedMessage(new AmqpValue("Hello World")); @@ -4233,5 +4233,52 @@ namespace Apache.Qpid.Proton.Client.Implementation peer.WaitForScriptToComplete(); } } + + [Test] + public void TestDeliveryReadWithLongTimeoutValue() + { + byte[] payload = CreateEncodedMessage(new AmqpValue("Hello World")); + + using (ProtonTestServer peer = new ProtonTestServer(loggerFactory)) + { + peer.ExpectSASLAnonymousConnect(); + peer.ExpectOpen().Respond(); + peer.ExpectBegin().Respond(); + peer.ExpectAttach().OfReceiver().Respond(); + peer.ExpectFlow().WithLinkCredit(10); + peer.RemoteTransfer().WithHandle(0) + .WithDeliveryId(0) + .WithDeliveryTag(new byte[] { 1 }) + .WithMore(false) + .WithSettled(true) + .WithMessageFormat(0) + .WithPayload(payload).AfterDelay(20).Queue(); + peer.Start(); + + string remoteAddress = peer.ServerAddress; + int remotePort = peer.ServerPort; + + logger.LogInformation("Test started, peer listening on: {0}:{1}", remoteAddress, remotePort); + + IClient container = IClient.Create(); + IConnection connection = container.Connect(remoteAddress, remotePort); + IStreamReceiver receiver = connection.OpenStreamReceiver("test-queue"); + + Assert.Throws<ArgumentOutOfRangeException>(() => receiver.Receive(TimeSpan.FromDays(50))); + + IStreamDelivery delivery = receiver.Receive(TimeSpan.FromDays(49)); + Assert.IsNotNull(delivery); + + peer.WaitForScriptToComplete(); + peer.ExpectDetach().Respond(); + peer.ExpectEnd().Respond(); + peer.ExpectClose().Respond(); + + receiver.Close(); + connection.Close(); + + peer.WaitForScriptToComplete(); + } + } } } \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org