diff --git a/Framework/Utils/Retry.cs b/Framework/Utils/Retry.cs index ec05ea66..5f325b3e 100644 --- a/Framework/Utils/Retry.cs +++ b/Framework/Utils/Retry.cs @@ -71,6 +71,10 @@ task(); return; } + catch (OperationCanceledException) + { + return; + } catch (Exception ex) { var failure = CaptureFailure(ex); diff --git a/Tests/CodexTests/BasicTests/OneClientTests.cs b/Tests/CodexTests/BasicTests/OneClientTests.cs index 908fb937..ef8c18b0 100644 --- a/Tests/CodexTests/BasicTests/OneClientTests.cs +++ b/Tests/CodexTests/BasicTests/OneClientTests.cs @@ -1,5 +1,7 @@ using CodexPlugin; +using FileUtils; using NUnit.Framework; +using System.Diagnostics; using Utils; namespace CodexTests.BasicTests @@ -10,11 +12,47 @@ namespace CodexTests.BasicTests [Test] public void OneClientTest() { - var primary = StartCodex(); + var node = StartCodex(); - PerformOneClientTest(primary); + PerformOneClientTest(node); - LogNodeStatus(primary); + LogNodeStatus(node); + } + + [Test] + public void InterruptUploadTest() + { + var tasks = new List>(); + for (var i = 0; i < 10; i++) + { + tasks.Add(Task.Run(() => RunInterruptUploadTest())); + } + Task.WaitAll(tasks.ToArray()); + + Assert.That(tasks.Select(t => t.Result).All(r => r == true)); + } + + private bool RunInterruptUploadTest() + { + var node = StartCodex(); + var file = GenerateTestFile(300.MB()); + + var process = StartCurlUploadProcess(node, file); + + Thread.Sleep(500); + process.Kill(); + Thread.Sleep(1000); + + var log = Ci.DownloadLog(node); + return !log.GetLinesContaining("Unhandled exception in async proc, aborting").Any(); + } + + private Process StartCurlUploadProcess(ICodexNode node, TrackedFile file) + { + var apiAddress = node.Container.GetAddress(CodexContainerRecipe.ApiPortTag); + var codexUrl = $"{apiAddress}/api/codex/v1/data"; + var filePath = file.Filename; + return Process.Start("curl", $"-X POST {codexUrl} -H \"Content-Type: application/octet-stream\" -T {filePath}"); } private void PerformOneClientTest(ICodexNode primary)