From bfdaef95d6e1dc96e1ad204c406e1201e399dbc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Mon, 24 May 2021 09:56:29 +0200 Subject: [PATCH] Fix OverflowException when estimating the progress remaining time (#404) Fix OverflowException when estimating the progress remaining time --- .../Unit/Progress/ProgressTests.cs | 26 +++++++++++++++++++ .../Widgets/Progress/ProgressTask.cs | 14 +++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Spectre.Console.Tests/Unit/Progress/ProgressTests.cs b/src/Spectre.Console.Tests/Unit/Progress/ProgressTests.cs index db32612..36f4067 100644 --- a/src/Spectre.Console.Tests/Unit/Progress/ProgressTests.cs +++ b/src/Spectre.Console.Tests/Unit/Progress/ProgressTests.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using Shouldly; using Spectre.Console.Testing; @@ -241,5 +242,30 @@ namespace Spectre.Console.Tests.Unit " \n" + // bottom padding "[?25h"); // show cursor } + + [Fact] + public void Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress() + { + // Given + var console = new TestConsole() + .Interactive(); + + var task = default(ProgressTask); + var progress = new Progress(console) + .Columns(new[] { new RemainingTimeColumn() }) + .AutoRefresh(false) + .AutoClear(false); + + // When + progress.Start(ctx => + { + task = ctx.AddTask("foo"); + task.Increment(double.Epsilon); + task.Increment(double.Epsilon); + }); + + // Then + task.RemainingTime.ShouldBe(TimeSpan.MaxValue); + } } } diff --git a/src/Spectre.Console/Widgets/Progress/ProgressTask.cs b/src/Spectre.Console/Widgets/Progress/ProgressTask.cs index 67afa2c..466ade2 100644 --- a/src/Spectre.Console/Widgets/Progress/ProgressTask.cs +++ b/src/Spectre.Console/Widgets/Progress/ProgressTask.cs @@ -286,20 +286,20 @@ namespace Spectre.Console } var speed = GetSpeed(); - if (speed == null) + if (speed == null || speed == 0) { return null; } - // If the speed is zero, the estimate below - // will return infinity (since it's a double), - // so let's set the speed to 1 in that case. - if (speed == 0) + // If the speed is near zero, the estimate below causes the + // TimeSpan creation to throw an OverflowException. Just return + // the maximum possible remaining time instead of overflowing. + var estimate = (MaxValue - Value) / speed.Value; + if (estimate > TimeSpan.MaxValue.TotalSeconds) { - speed = 1; + return TimeSpan.MaxValue; } - var estimate = (MaxValue - Value) / speed.Value; return TimeSpan.FromSeconds(estimate); } }