From 155923a8d74c24cf734e3ba6170136c19f596942 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 14:07:37 +0600 Subject: [PATCH 01/11] separate tests to use separate instances of test apps --- .../DotnetSuggestEndToEndTests.cs | 57 ++++++++-- .../SuggestionStoreTests.cs | 107 ++++++++++++++++++ 2 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs diff --git a/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs b/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs index 7e08fc8d65..2264d226cd 100644 --- a/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs +++ b/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs @@ -10,12 +10,13 @@ using static System.Environment; using Process = System.CommandLine.Tests.Utility.Process; -namespace System.CommandLine.Suggest.Tests +namespace System.CommandLine.Suggest.Tests { public class DotnetSuggestEndToEndTests : IDisposable { private readonly ITestOutputHelper _output; private readonly FileInfo _endToEndTestApp; + private readonly FileInfo _waitAndFailTestApp; private readonly FileInfo _dotnetSuggest; private readonly (string, string)[] _environmentVariables; private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory; @@ -25,14 +26,15 @@ public DotnetSuggestEndToEndTests(ITestOutputHelper output) { _output = output; - // delete sentinel files for EndToEndTestApp in order to trigger registration when it's run + // delete sentinel files for TestApps in order to trigger registration when it's run var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files")); if (sentinelsDir.Exists) { - var sentinels = sentinelsDir.GetFiles("*EndToEndTestApp*"); + var sentinelsEndToEnd = sentinelsDir.GetFiles("*EndToEndTestApp*"); + var sentinelsWaitAndFail = sentinelsDir.GetFiles("*WaitAndFailTestApp*"); - foreach (var sentinel in sentinels) + foreach (var sentinel in sentinelsEndToEnd.Concat(sentinelsWaitAndFail)) { sentinel.Delete(); } @@ -43,12 +45,16 @@ public DotnetSuggestEndToEndTests(ITestOutputHelper output) "TestAssets"); _endToEndTestApp = new DirectoryInfo(currentDirectory) - .GetFiles("EndToEndTestApp".ExecutableName()) - .SingleOrDefault(); + .GetFiles("EndToEndTestApp".ExecutableName()) + .SingleOrDefault(); + _waitAndFailTestApp = new DirectoryInfo(currentDirectory) + .GetFiles("WaitAndFailTestApp".ExecutableName()) + .SingleOrDefault(); + _dotnetSuggest = new DirectoryInfo(currentDirectory) - .GetFiles("dotnet-suggest".ExecutableName()) - .SingleOrDefault(); + .GetFiles("dotnet-suggest".ExecutableName()) + .SingleOrDefault(); PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome(); @@ -156,5 +162,40 @@ public void Dotnet_suggest_provides_suggestions_for_app_with_only_commandname() .Should() .Be($"--apple{NewLine}--banana{NewLine}--cherry{NewLine}--durian{NewLine}--help{NewLine}--version{NewLine}-?{NewLine}-h{NewLine}/?{NewLine}/h{NewLine}"); } + + [ReleaseBuildOnlyFact] + public void Dotnet_suggest_fails_to_provide_suggestions_because_app_faulted() + { + // run "dotnet-suggest register" in explicit way + Process.RunToCompletion( + _dotnetSuggest.FullName, + $"register --command-path \"{_waitAndFailTestApp.FullName}\"", + stdOut: s => _output.WriteLine(s), + stdErr: s => _output.WriteLine(s), + environmentVariables: _environmentVariables).Should().Be(0); + + var stdOut = new StringBuilder(); + var stdErr = new StringBuilder(); + + var commandLineToComplete = "a"; + + Process.RunToCompletion( + _dotnetSuggest.FullName, + $"get -e \"{_waitAndFailTestApp.FullName}\" --position {commandLineToComplete.Length} -- \"{commandLineToComplete}\"", + stdOut: value => stdOut.AppendLine(value), + stdErr: value => stdErr.AppendLine(value), + environmentVariables: _environmentVariables); + + _output.WriteLine($"stdOut:{NewLine}{stdOut}{NewLine}"); + _output.WriteLine($"stdErr:{NewLine}{stdErr}{NewLine}"); + + stdErr.ToString() + .Should() + .BeEmpty(); + + stdOut.ToString() + .Should() + .BeEmpty(); + } } } diff --git a/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs new file mode 100644 index 0000000000..b7e15047d1 --- /dev/null +++ b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs @@ -0,0 +1,107 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.CommandLine.Tests.Utility; +using System.IO; +using System.Linq; +using FluentAssertions; +using Xunit.Abstractions; +using static System.Environment; + +namespace System.CommandLine.Suggest.Tests +{ + public class SuggestionStoreTests : IDisposable + { + protected readonly ITestOutputHelper Output; + protected readonly FileInfo EndToEndTestApp; + protected readonly FileInfo WaitAndFailTestApp; + protected readonly FileInfo DotnetSuggest; + protected readonly (string, string)[] _environmentVariables; + private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory; + private static string _testRoot; + + public SuggestionStoreTests(ITestOutputHelper output) + { + Output = output; + + // delete sentinel files for TestApps in order to trigger registration when it's run + var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files")); + + if (sentinelsDir.Exists) + { + var sentinels = sentinelsDir + .EnumerateFiles() + .Where(f => f.Name.Contains("EndToEndTestApp") || f.Name.Contains("WaitAndFailTestApp")); + + foreach (var sentinel in sentinels) + { + sentinel.Delete(); + } + } + + var currentDirectory = Path.Combine( + Directory.GetCurrentDirectory(), + "TestAssets"); + + EndToEndTestApp = new DirectoryInfo(currentDirectory) + .GetFiles("EndToEndTestApp".ExecutableName()) + .SingleOrDefault(); + + WaitAndFailTestApp = new DirectoryInfo(currentDirectory) + .GetFiles("WaitAndFailTestApp".ExecutableName()) + .SingleOrDefault(); + + DotnetSuggest = new DirectoryInfo(currentDirectory) + .GetFiles("dotnet-suggest".ExecutableName()) + .SingleOrDefault(); + + PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome(); + + _environmentVariables = new[] { + ("DOTNET_ROOT", _dotnetHostDir.FullName), + ("INTERNAL_TEST_DOTNET_SUGGEST_HOME", _testRoot)}; + } + + public void Dispose() + { + if (_testRoot != null && Directory.Exists(_testRoot)) + { + Directory.Delete(_testRoot, recursive: true); + } + } + + private static void PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome() + { + _testRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(_testRoot); + } + + [ReleaseBuildOnlyFact] + public void GetCompletions_obtains_suggestions_successfully() + { + var store = new SuggestionStore(); + var completions = store.GetCompletions(EndToEndTestApp.FullName, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); + completions.Should().Be($"--apple{NewLine}--banana{NewLine}--durian{NewLine}"); + } + + [ReleaseBuildOnlyFact] + public void GetCompletions_fails_to_obtain_suggestions_because_app_takes_too_long() + { + var store = new SuggestionStore(); + var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(2000).ToString(); + var completions = store + .GetCompletions(WaitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); + completions.Should().BeEmpty(); + } + + [ReleaseBuildOnlyFact] + public void GetCompletions_fails_to_obtain_suggestions_because_app_exited_with_nonzero_code() + { + var store = new SuggestionStore(); + var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(0).ToString(); + var completions = store + .GetCompletions(WaitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); + completions.Should().BeEmpty(); + } + } +} From dfba8b4534fbdfaa15f023639600da20e75e1b98 Mon Sep 17 00:00:00 2001 From: baradgur Date: Tue, 11 Apr 2023 21:03:33 +0600 Subject: [PATCH 02/11] SuggestionStore::GetCompletions to check exit code of invoked application Fix #2147 --- src/System.CommandLine.Suggest/SuggestionStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs index ac93972eb1..d624d66f88 100644 --- a/src/System.CommandLine.Suggest/SuggestionStore.cs +++ b/src/System.CommandLine.Suggest/SuggestionStore.cs @@ -44,7 +44,7 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument Task readToEndTask = process.StandardOutput.ReadToEndAsync(); - if (readToEndTask.Wait(timeout)) + if (readToEndTask.Wait(timeout) && process.HasExited && process.ExitCode == 0) { result = readToEndTask.Result; } From 976e4c0a0f343d849f426e092f3c7a8468047239 Mon Sep 17 00:00:00 2001 From: baradgur Date: Thu, 13 Apr 2023 02:31:30 +0600 Subject: [PATCH 03/11] SuggestionStore::GetCompletions to check exit code of invoked application fixed Fix #2147 --- src/System.CommandLine.Suggest/SuggestionStore.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs index d624d66f88..b92246c8e1 100644 --- a/src/System.CommandLine.Suggest/SuggestionStore.cs +++ b/src/System.CommandLine.Suggest/SuggestionStore.cs @@ -42,11 +42,9 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument { process.Start(); - Task readToEndTask = process.StandardOutput.ReadToEndAsync(); - - if (readToEndTask.Wait(timeout) && process.HasExited && process.ExitCode == 0) + if (process.WaitForExit(timeout) && process.ExitCode == 0) { - result = readToEndTask.Result; + result = process.StandardOutput.ReadToEnd(); } else { From 1813b560075a9c1a09c2803eec6480c130d7ea44 Mon Sep 17 00:00:00 2001 From: baradgur Date: Thu, 13 Apr 2023 15:00:48 +0600 Subject: [PATCH 04/11] added tests to SuggestionStore::GetCompletions Fix #2147 --- .../TestsWithTestApps.cs | 74 +++++++++++++++++++ .../WaitAndFailTestApp/Program.cs | 25 +++++++ .../WaitAndFailTestApp.csproj | 12 +++ .../dotnet-suggest.Tests.csproj | 11 +++ 4 files changed, 122 insertions(+) create mode 100644 src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs create mode 100644 src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs create mode 100644 src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj diff --git a/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs b/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs new file mode 100644 index 0000000000..485c9160a2 --- /dev/null +++ b/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs @@ -0,0 +1,74 @@ +using System.IO; +using System.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace System.CommandLine.Suggest.Tests; + +[Collection("TestsWithTestApps")] +public class TestsWithTestApps : IDisposable +{ + protected readonly ITestOutputHelper Output; + protected readonly FileInfo EndToEndTestApp; + protected readonly FileInfo WaitAndFailTestApp; + protected readonly FileInfo DotnetSuggest; + protected readonly (string, string)[] EnvironmentVariables; + private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory; + private static string _testRoot; + + protected TestsWithTestApps(ITestOutputHelper output) + { + Output = output; + + // delete sentinel files for TestApps in order to trigger registration when it's run + var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files")); + + if (sentinelsDir.Exists) + { + var sentinels = sentinelsDir + .EnumerateFiles() + .Where(f => f.Name.Contains("EndToEndTestApp") || f.Name.Contains("WaitAndFailTestApp")); + + foreach (var sentinel in sentinels) + { + sentinel.Delete(); + } + } + + var currentDirectory = Path.Combine( + Directory.GetCurrentDirectory(), + "TestAssets"); + + EndToEndTestApp = new DirectoryInfo(currentDirectory) + .GetFiles("EndToEndTestApp".ExecutableName()) + .SingleOrDefault(); + + WaitAndFailTestApp = new DirectoryInfo(currentDirectory) + .GetFiles("WaitAndFailTestApp".ExecutableName()) + .SingleOrDefault(); + + DotnetSuggest = new DirectoryInfo(currentDirectory) + .GetFiles("dotnet-suggest".ExecutableName()) + .SingleOrDefault(); + + PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome(); + + EnvironmentVariables = new[] { + ("DOTNET_ROOT", _dotnetHostDir.FullName), + ("INTERNAL_TEST_DOTNET_SUGGEST_HOME", _testRoot)}; + } + + public void Dispose() + { + if (_testRoot != null && Directory.Exists(_testRoot)) + { + Directory.Delete(_testRoot, recursive: true); + } + } + + private static void PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome() + { + _testRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(_testRoot); + } +} \ No newline at end of file diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs new file mode 100644 index 0000000000..d1d22b38ab --- /dev/null +++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; + +namespace WaitAndFailTestApp; + +public class Program +{ + private static TimeSpan defaultWait = TimeSpan.FromMilliseconds(3000); + + //we should not be able to receive any suggestion from this test app, + //so we are not constructing it using CliConfiguration + + static async Task Main(string[] args) + { + var waitPeriod = args.Length > 0 && int.TryParse(args[0], out var millisecondsToWaitParsed) + ? TimeSpan.FromMilliseconds(millisecondsToWaitParsed) + : defaultWait; + + await Task.Delay(waitPeriod); + Environment.ExitCode = 1; + + Console.WriteLine("this 'suggestion' is provided too late and/or with invalid app exit code"); + } +} + diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj new file mode 100644 index 0000000000..186b884e98 --- /dev/null +++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj @@ -0,0 +1,12 @@ + + + + + + + + Exe + net7.0 + + + diff --git a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj index f1711a10e1..2869f2abf6 100644 --- a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj +++ b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj @@ -13,6 +13,11 @@ + + + + + @@ -67,6 +72,12 @@ + + + + + + From 8cb5814c37931f8092cfc4dc3420dbf3570ffa0d Mon Sep 17 00:00:00 2001 From: baradgur Date: Fri, 14 Apr 2023 18:17:37 +0600 Subject: [PATCH 05/11] use async read for standard output for SuggestionStore::GetCompletions Fix #2147 --- src/System.CommandLine.Suggest/SuggestionStore.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs index b92246c8e1..0a6c8b6649 100644 --- a/src/System.CommandLine.Suggest/SuggestionStore.cs +++ b/src/System.CommandLine.Suggest/SuggestionStore.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; +using System.Text; using System.Threading.Tasks; namespace System.CommandLine.Suggest @@ -41,10 +42,20 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument }) { process.Start(); - + process.BeginOutputReadLine(); + + var stringBuilder = new StringBuilder(); + process.OutputDataReceived += (sender, eventArgs) => + { + if (eventArgs.Data != null) + { + stringBuilder.AppendLine(eventArgs.Data); + } + }; + if (process.WaitForExit(timeout) && process.ExitCode == 0) { - result = process.StandardOutput.ReadToEnd(); + result = stringBuilder.ToString(); } else { From d4d6c7ad2dd85b8ae96b1a91b61f36240116da41 Mon Sep 17 00:00:00 2001 From: baradgur Date: Fri, 14 Apr 2023 20:04:15 +0600 Subject: [PATCH 06/11] stopping async read in SuggestionStore::GetCompletions gracefully Fix #2147 --- src/System.CommandLine.Suggest/SuggestionStore.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs index 0a6c8b6649..d77e547f5a 100644 --- a/src/System.CommandLine.Suggest/SuggestionStore.cs +++ b/src/System.CommandLine.Suggest/SuggestionStore.cs @@ -41,8 +41,8 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument StartInfo = processStartInfo }) { + process.Start(); - process.BeginOutputReadLine(); var stringBuilder = new StringBuilder(); process.OutputDataReceived += (sender, eventArgs) => @@ -52,13 +52,17 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument stringBuilder.AppendLine(eventArgs.Data); } }; - + process.BeginOutputReadLine(); if (process.WaitForExit(timeout) && process.ExitCode == 0) { + process.CancelOutputRead(); result = stringBuilder.ToString(); } else { +#if DEBUG + Program.LogDebug($"Killing the process after a timeout. Process exit code: {process.ExitCode}"); +#endif process.Kill(); } } From 5728887e3e2c4a28cea2546e4ad768c09bf59556 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 14:07:37 +0600 Subject: [PATCH 07/11] separate tests to use separate instances of test apps --- .../TestsWithTestApps.cs | 74 ------------------- .../SuggestionStore.cs | 2 +- 2 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs diff --git a/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs b/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs deleted file mode 100644 index 485c9160a2..0000000000 --- a/src/System.CommandLine.Suggest.Tests/TestsWithTestApps.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.IO; -using System.Linq; -using Xunit; -using Xunit.Abstractions; - -namespace System.CommandLine.Suggest.Tests; - -[Collection("TestsWithTestApps")] -public class TestsWithTestApps : IDisposable -{ - protected readonly ITestOutputHelper Output; - protected readonly FileInfo EndToEndTestApp; - protected readonly FileInfo WaitAndFailTestApp; - protected readonly FileInfo DotnetSuggest; - protected readonly (string, string)[] EnvironmentVariables; - private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory; - private static string _testRoot; - - protected TestsWithTestApps(ITestOutputHelper output) - { - Output = output; - - // delete sentinel files for TestApps in order to trigger registration when it's run - var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files")); - - if (sentinelsDir.Exists) - { - var sentinels = sentinelsDir - .EnumerateFiles() - .Where(f => f.Name.Contains("EndToEndTestApp") || f.Name.Contains("WaitAndFailTestApp")); - - foreach (var sentinel in sentinels) - { - sentinel.Delete(); - } - } - - var currentDirectory = Path.Combine( - Directory.GetCurrentDirectory(), - "TestAssets"); - - EndToEndTestApp = new DirectoryInfo(currentDirectory) - .GetFiles("EndToEndTestApp".ExecutableName()) - .SingleOrDefault(); - - WaitAndFailTestApp = new DirectoryInfo(currentDirectory) - .GetFiles("WaitAndFailTestApp".ExecutableName()) - .SingleOrDefault(); - - DotnetSuggest = new DirectoryInfo(currentDirectory) - .GetFiles("dotnet-suggest".ExecutableName()) - .SingleOrDefault(); - - PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome(); - - EnvironmentVariables = new[] { - ("DOTNET_ROOT", _dotnetHostDir.FullName), - ("INTERNAL_TEST_DOTNET_SUGGEST_HOME", _testRoot)}; - } - - public void Dispose() - { - if (_testRoot != null && Directory.Exists(_testRoot)) - { - Directory.Delete(_testRoot, recursive: true); - } - } - - private static void PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome() - { - _testRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(_testRoot); - } -} \ No newline at end of file diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs index d77e547f5a..9e41b44402 100644 --- a/src/System.CommandLine.Suggest/SuggestionStore.cs +++ b/src/System.CommandLine.Suggest/SuggestionStore.cs @@ -38,7 +38,7 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument using (var process = new Process { - StartInfo = processStartInfo + StartInfo = processStartInfo, }) { From 3005982b30a952c3002f4b6656636bd1bcdd16b8 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 15:10:00 +0600 Subject: [PATCH 08/11] fix restore packages fo WaitAndFailTestApp --- .../WaitAndFailTestApp/WaitAndFailTestApp.csproj | 2 +- .../dotnet-suggest.Tests.csproj | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj index 186b884e98..76add0d5a9 100644 --- a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj +++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj @@ -6,7 +6,7 @@ Exe - net7.0 + $(TargetFrameworkForNETSDK) diff --git a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj index 0cae940c54..4a314f6eae 100644 --- a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj +++ b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj @@ -58,6 +58,8 @@ + + From 3a6752162b03cd0401b2c9ab48ab6a328adaa778 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 15:28:39 +0600 Subject: [PATCH 09/11] run "dotnet-suggest register" in explicit way --- .../SuggestionStoreTests.cs | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs index b7e15047d1..1f33b50a6e 100644 --- a/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs +++ b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs @@ -12,17 +12,17 @@ namespace System.CommandLine.Suggest.Tests { public class SuggestionStoreTests : IDisposable { - protected readonly ITestOutputHelper Output; - protected readonly FileInfo EndToEndTestApp; - protected readonly FileInfo WaitAndFailTestApp; - protected readonly FileInfo DotnetSuggest; + protected readonly ITestOutputHelper _output; + protected readonly FileInfo _endToEndTestApp; + protected readonly FileInfo _waitAndFailTestApp; + protected readonly FileInfo _dotnetSuggest; protected readonly (string, string)[] _environmentVariables; private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory; private static string _testRoot; public SuggestionStoreTests(ITestOutputHelper output) { - Output = output; + _output = output; // delete sentinel files for TestApps in order to trigger registration when it's run var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files")); @@ -43,15 +43,15 @@ public SuggestionStoreTests(ITestOutputHelper output) Directory.GetCurrentDirectory(), "TestAssets"); - EndToEndTestApp = new DirectoryInfo(currentDirectory) + _endToEndTestApp = new DirectoryInfo(currentDirectory) .GetFiles("EndToEndTestApp".ExecutableName()) .SingleOrDefault(); - WaitAndFailTestApp = new DirectoryInfo(currentDirectory) + _waitAndFailTestApp = new DirectoryInfo(currentDirectory) .GetFiles("WaitAndFailTestApp".ExecutableName()) .SingleOrDefault(); - DotnetSuggest = new DirectoryInfo(currentDirectory) + _dotnetSuggest = new DirectoryInfo(currentDirectory) .GetFiles("dotnet-suggest".ExecutableName()) .SingleOrDefault(); @@ -79,8 +79,16 @@ private static void PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome() [ReleaseBuildOnlyFact] public void GetCompletions_obtains_suggestions_successfully() { + // run "dotnet-suggest register" in explicit way + Process.RunToCompletion( + _dotnetSuggest.FullName, + $"register --command-path \"{_endToEndTestApp.FullName}\"", + stdOut: s => _output.WriteLine(s), + stdErr: s => _output.WriteLine(s), + environmentVariables: _environmentVariables).Should().Be(0); + var store = new SuggestionStore(); - var completions = store.GetCompletions(EndToEndTestApp.FullName, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); + var completions = store.GetCompletions(_endToEndTestApp.FullName, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); completions.Should().Be($"--apple{NewLine}--banana{NewLine}--durian{NewLine}"); } @@ -90,7 +98,7 @@ public void GetCompletions_fails_to_obtain_suggestions_because_app_takes_too_lon var store = new SuggestionStore(); var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(2000).ToString(); var completions = store - .GetCompletions(WaitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); + .GetCompletions(_waitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); completions.Should().BeEmpty(); } @@ -100,8 +108,33 @@ public void GetCompletions_fails_to_obtain_suggestions_because_app_exited_with_n var store = new SuggestionStore(); var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(0).ToString(); var completions = store - .GetCompletions(WaitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); + .GetCompletions(_waitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000)); completions.Should().BeEmpty(); } + + [ReleaseBuildOnlyFact] + public void GetCompletions_throws_when_exeFileName_is_null() + { + var store = new SuggestionStore(); + var act = () => store.GetCompletions(null, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); + act.Should().Throw(); + } + + [ReleaseBuildOnlyFact] + public void GetCompletions_throws_when_exeFileName_is_empty() + { + var store = new SuggestionStore(); + var act = () => store.GetCompletions(" ", "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); + act.Should().Throw(); + } + + [ReleaseBuildOnlyFact] + public void GetCompletions_throws_when_exeFile_does_not_exist() + { + var store = new SuggestionStore(); + var act = () => store + .GetCompletions("thisExecutableDoesNotExist.exe", "[suggest:1] \"a\"", TimeSpan.FromSeconds(1)); + act.Should().Throw(); + } } } From e826c60598f07629da66acf1c22f2460a6435848 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 16:17:11 +0600 Subject: [PATCH 10/11] trying to use .net60 for test apps --- .../EndToEndTestApp/EndToEndTestApp.csproj | 2 +- .../WaitAndFailTestApp/WaitAndFailTestApp.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj index 76add0d5a9..9a3eb54d35 100644 --- a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj +++ b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj @@ -6,7 +6,7 @@ Exe - $(TargetFrameworkForNETSDK) + net6.0 diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj index 76add0d5a9..9a3eb54d35 100644 --- a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj +++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj @@ -6,7 +6,7 @@ Exe - $(TargetFrameworkForNETSDK) + net6.0 From 9a0642572154c8b8e2b6df35963ba529de3fc4d9 Mon Sep 17 00:00:00 2001 From: baradgur Date: Sun, 28 Jan 2024 16:24:38 +0600 Subject: [PATCH 11/11] trying to use .net80 explicitly for test apps --- .../EndToEndTestApp/EndToEndTestApp.csproj | 2 +- .../WaitAndFailTestApp/WaitAndFailTestApp.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj index 9a3eb54d35..98fa0e21ad 100644 --- a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj +++ b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj @@ -6,7 +6,7 @@ Exe - net6.0 + net8.0 diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj index 9a3eb54d35..98fa0e21ad 100644 --- a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj +++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj @@ -6,7 +6,7 @@ Exe - net6.0 + net8.0