< Summary

Information
Class: Amusoft.DotnetNew.Tests.CLI.LoggedDotnetCli
Assembly: Amusoft.DotnetNew.Tests
File(s): /home/runner/work/Amusoft.DotnetNew.Tests/Amusoft.DotnetNew.Tests/src/Amusoft.DotnetNew.Tests/CLI/LoggedDotnetCli.cs
Tag: 127_14865883074
Line coverage
100%
Covered lines: 5
Uncovered lines: 0
Coverable lines: 5
Total lines: 134
Line coverage: 100%
Branch coverage
83%
Covered branches: 5
Total branches: 6
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
RunDotnetCommandAsync()83.33%66100%

File(s)

/home/runner/work/Amusoft.DotnetNew.Tests/Amusoft.DotnetNew.Tests/src/Amusoft.DotnetNew.Tests/CLI/LoggedDotnetCli.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Diagnostics;
 4using System.Diagnostics.CodeAnalysis;
 5using System.Linq;
 6using System.Runtime.InteropServices;
 7using System.Text;
 8using System.Threading;
 9using System.Threading.Tasks;
 10using Amusoft.DotnetNew.Tests.Diagnostics;
 11using Amusoft.DotnetNew.Tests.Extensions;
 12using Amusoft.DotnetNew.Tests.Interfaces;
 13using Amusoft.DotnetNew.Tests.Scopes;
 14using CliWrap;
 15using CliWrap.Buffered;
 16using CommandResult = Amusoft.DotnetNew.Tests.Diagnostics.CommandResult;
 17
 18namespace Amusoft.DotnetNew.Tests.CLI;
 19
 20internal static class LoggedDotnetCli
 21{
 22  internal static async Task<bool> RunDotnetCommandAsync(string arguments, CancellationToken cancellationToken, DotnetCo
 23  {
 1324    if(commandOptions?.WorkingDirectory != null)
 125      LoggingScope.Current?.AddResult(new TextResult($"Using working directory: {commandOptions.WorkingDirectory}"));
 26
 1327    var runner = new LocalProcessRunner();
 28    // var runner = new CliWrapRunner();
 1329    return await runner.RunAsync(arguments, commandOptions, cancellationToken, acceptAsSuccess).ConfigureAwait(false);
 1330  }
 31}
 32
 33[ExcludeFromCodeCoverage]
 34internal class CliWrapRunner : IProcessRunner
 35{
 36  public async Task<bool> RunAsync(string arguments, DotnetCommandOptions? commandOptions, CancellationToken cancellatio
 37  {
 38    var env = new Dictionary<string, string?>()
 39    {
 40      ["DOTNET_CLI_UI_LANGUAGE"] = "en",
 41    };
 42
 43    DiagnosticScope.TryAddContent($"dotnet {arguments}");
 44    LoggingScope.TryAddInvocation($"dotnet {arguments}");
 45
 46    var command = Cli.Wrap("dotnet")
 47      .WithWorkingDirectory(commandOptions.WorkingDirectory)
 48      .WithEnvironmentVariables(env)
 49      .WithArguments(arguments)
 50      .WithValidation(CommandResultValidation.None);
 51
 52    if (commandOptions?.WorkingDirectory != null)
 53      command.WithWorkingDirectory(commandOptions.WorkingDirectory);
 54
 55    var bufferedCommandResult = await command
 56      .ExecuteBufferedAsync(cancellationToken)
 57      .ConfigureAwait(false);
 58
 59    DiagnosticScope.TryAddJson(new
 60    {
 61      Output = bufferedCommandResult.StandardOutput,
 62      Error = bufferedCommandResult.StandardError,
 63    });
 64    LoggingScope.TryAddResult(bufferedCommandResult.ToCommandResult());
 65
 66    return bufferedCommandResult.IsSuccess || successStatusCodes.Contains(bufferedCommandResult.ExitCode);
 67  }
 68}
 69
 70[ExcludeFromCodeCoverage]
 71internal class LocalProcessRunner : IProcessRunner
 72{
 73  public async Task<bool> RunAsync(string arguments, DotnetCommandOptions? commandOptions, CancellationToken cancellatio
 74  {
 75    DiagnosticScope.TryAddContent($"dotnet {arguments}");
 76    LoggingScope.TryAddInvocation($"dotnet {arguments}");
 77
 78    var psi = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
 79      ? new ProcessStartInfo("dotnet", arguments)
 80      {
 81        RedirectStandardOutput = true,
 82        RedirectStandardError = true,
 83        UseShellExecute = false,
 84        CreateNoWindow = true,
 85        LoadUserProfile = false,
 86      }
 87      : new ProcessStartInfo("dotnet", arguments)
 88      {
 89        RedirectStandardOutput = true,
 90        RedirectStandardError = true,
 91        UseShellExecute = false,
 92        CreateNoWindow = true,
 93      };
 94
 95    psi.Environment.Add("DOTNET_CLI_UI_LANGUAGE", "en");
 96    if (commandOptions != null)
 97      psi.WorkingDirectory = commandOptions.WorkingDirectory;
 98
 99    var output = new StringBuilder();
 100    var error = new StringBuilder();
 101    var process = new Process();
 102    process.StartInfo = psi;
 103    process.OutputDataReceived += (sender, args) => output.AppendLine(args.Data);
 104    process.ErrorDataReceived += (sender, args) => error.AppendLine(args.Data);
 105    process.Start();
 106    process.BeginOutputReadLine();
 107    process.BeginErrorReadLine();
 108
 109    var sw = new Stopwatch();
 110    sw.Restart();
 111    try
 112    {
 113      await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
 114
 115      sw.Stop();
 116
 117      var success = process.HasExited && (process.ExitCode == 0 || successStatusCodes.Contains(process.ExitCode));
 118      DiagnosticScope.TryAddJson(new
 119      {
 120        Output = output.ToString(),
 121        Error = error.ToString(),
 122      });
 123      LoggingScope.TryAddResult(new CommandResult(process.ExitCode, output.ToString(), error.ToString(), success, sw.Ela
 124
 125      return success;
 126    }
 127    catch (OperationCanceledException)
 128    {
 129      DiagnosticScope.TryAddContent("Operation cancelled");
 130      LoggingScope.TryAddResult(new TextResult("Process aborted"));
 131      return false;
 132    }
 133  }
 134}

Methods/Properties

RunDotnetCommandAsync()