Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/BuiltInCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,9 @@ public ICommand SetCommandArgs(string commandArgs)
{
throw new NotImplementedException();
}

public ICommand StandardOutputEncoding(Encoding encoding)
{
throw new NotImplementedException();
}
}
6 changes: 6 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ public ICommand EnvironmentVariable(string name, string? value)
return this;
}

public ICommand StandardOutputEncoding(Encoding encoding)
{
_process.StartInfo.StandardOutputEncoding = encoding;
return this;
}

public ICommand CaptureStdOut()
{
ThrowIfRunning();
Expand Down
2 changes: 2 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/ICommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface ICommand

ICommand SetCommandArgs(string commandArgs);

ICommand StandardOutputEncoding(Encoding encoding);

string CommandName { get; }

string CommandArgs { get; }
Expand Down
10 changes: 9 additions & 1 deletion src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ public VirtualProjectBuildingCommand(
public override int Execute()
{
Debug.Assert(!(NoRestore && NoBuild));

var consoleLogger = RunCommand.MakeTerminalLogger(Verbosity);
var binaryLogger = GetBinaryLogger(BinaryLoggerArgs);

Expand Down Expand Up @@ -625,6 +624,15 @@ public static void WriteProjectFile(

""");

var targetDirectory = Path.GetDirectoryName(targetFilePath) ?? "";
writer.WriteLine($"""
<ItemGroup>
<RuntimeHostConfigurationOption Include="EntryPointFilePath" Value="{EscapeValue(targetFilePath)}" />
<RuntimeHostConfigurationOption Include="EntryPointFileDirectoryPath" Value="{EscapeValue(targetDirectory)}" />
</ItemGroup>

""");

foreach (var sdk in sdkDirectives)
{
WriteImport(writer, "Sdk.targets", sdk);
Expand Down
13 changes: 13 additions & 0 deletions test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public abstract class TestCommand
public Action<string>? CommandOutputHandler { get; set; }
public Action<Process>? ProcessStartedHandler { get; set; }

public Encoding? StandardOutputEncoding { get; set; }

protected TestCommand(ITestOutputHelper log)
{
Log = log;
Expand Down Expand Up @@ -57,6 +59,12 @@ public TestCommand WithStandardInput(string stdin)
return this;
}

public TestCommand WithStandardOutputEncoding(Encoding encoding)
{
StandardOutputEncoding = encoding;
return this;
}

/// <summary>
/// Instructs not to escape the arguments when launching command.
/// This may be used to pass ready arguments line as single string argument.
Expand Down Expand Up @@ -153,6 +161,11 @@ public virtual CommandResult Execute(IEnumerable<string> args)
{
Log.WriteLine($"❌{line}");
});

if (StandardOutputEncoding is not null)
{
command.StandardOutputEncoding(StandardOutputEncoding);
}

string fileToShow = Path.GetFileNameWithoutExtension(spec.FileName!).Equals("dotnet", StringComparison.OrdinalIgnoreCase) ?
"dotnet" :
Expand Down
123 changes: 122 additions & 1 deletion test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.Versioning;
Expand Down Expand Up @@ -1246,6 +1246,11 @@ public void Api()
<Compile Include="{programPath}" />
</ItemGroup>

<ItemGroup>
<RuntimeHostConfigurationOption Include="EntryPointFilePath" Value="{programPath}" />
<RuntimeHostConfigurationOption Include="EntryPointFileDirectoryPath" Value="{testInstance.Path}" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Import Project="Sdk.targets" Sdk="Aspire.Hosting.Sdk" Version="9.1.0" />

Expand Down Expand Up @@ -1329,6 +1334,11 @@ public void Api_Diagnostic_01()
<Compile Include="{programPath}" />
</ItemGroup>

<ItemGroup>
<RuntimeHostConfigurationOption Include="EntryPointFilePath" Value="{programPath}" />
<RuntimeHostConfigurationOption Include="EntryPointFileDirectoryPath" Value="{testInstance.Path}" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<!--
Expand Down Expand Up @@ -1415,6 +1425,11 @@ public void Api_Diagnostic_02()
<Compile Include="{programPath}" />
</ItemGroup>

<ItemGroup>
<RuntimeHostConfigurationOption Include="EntryPointFilePath" Value="{programPath}" />
<RuntimeHostConfigurationOption Include="EntryPointFileDirectoryPath" Value="{testInstance.Path}" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<!--
Expand Down Expand Up @@ -1470,4 +1485,110 @@ public void Api_Error()
.And.HaveStdOutContaining("Unknown1")
.And.HaveStdOutContaining("Unknown2");
}

[Fact]
public void EntryPointFilePath()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var filePath = Path.Join(testInstance.Path, "Program.cs");
File.WriteAllText(filePath, """"
var entryPointFilePath = AppContext.GetData("EntryPointFilePath") as string;
Console.WriteLine($"""EntryPointFilePath: {entryPointFilePath}""");
"""");

new DotnetCommand(Log, "run", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFilePath: {filePath}");
}

[Fact]
public void EntryPointFileDirectoryPath()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """"
var entryPointFileDirectoryPath = AppContext.GetData("EntryPointFileDirectoryPath") as string;
Console.WriteLine($"""EntryPointFileDirectoryPath: {entryPointFileDirectoryPath}""");
"""");

new DotnetCommand(Log, "run", "Program.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFileDirectoryPath: {testInstance.Path}");
}

[Fact]
public void EntryPointFilePath_WithRelativePath()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var fileName = "Program.cs";
File.WriteAllText(Path.Join(testInstance.Path, fileName), """
var entryPointFilePath = AppContext.GetData("EntryPointFilePath") as string;
Console.WriteLine($"EntryPointFilePath: {entryPointFilePath}");
""");

var relativePath = Path.GetRelativePath(Directory.GetCurrentDirectory(), Path.Join(testInstance.Path, fileName));
new DotnetCommand(Log, "run", relativePath)
.WithWorkingDirectory(Directory.GetCurrentDirectory())
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFilePath: {Path.GetFullPath(relativePath)}");
}

[Fact]
public void EntryPointFilePath_WithSpacesInPath()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var dirWithSpaces = Path.Join(testInstance.Path, "dir with spaces");
Directory.CreateDirectory(dirWithSpaces);
var filePath = Path.Join(dirWithSpaces, "Program.cs");
File.WriteAllText(filePath, """
var entryPointFilePath = AppContext.GetData("EntryPointFilePath") as string;
Console.WriteLine($"EntryPointFilePath: {entryPointFilePath}");
""");

new DotnetCommand(Log, "run", filePath)
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFilePath: {filePath}");
}

[Fact]
public void EntryPointFileDirectoryPath_WithDotSlash()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var fileName = "Program.cs";
File.WriteAllText(Path.Join(testInstance.Path, fileName), """
var entryPointFileDirectoryPath = AppContext.GetData("EntryPointFileDirectoryPath") as string;
Console.WriteLine($"EntryPointFileDirectoryPath: {entryPointFileDirectoryPath}");
""");

new DotnetCommand(Log, "run", $"./{fileName}")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFileDirectoryPath: {testInstance.Path}");
}

[Fact]
public void EntryPointFilePath_WithUnicodeCharacters()
{
var testInstance = _testAssetsManager.CreateTestDirectory();
var unicodeFileName = "Программа.cs";
var filePath = Path.Join(testInstance.Path, unicodeFileName);
File.WriteAllText(filePath, """
var entryPointFilePath = AppContext.GetData("EntryPointFilePath") as string;
Console.WriteLine($"EntryPointFilePath: {entryPointFilePath}");
""");

new DotnetCommand(Log, "run", unicodeFileName)
.WithWorkingDirectory(testInstance.Path)
.WithStandardOutputEncoding(Encoding.UTF8)
.Execute()
.Should().Pass()
.And.HaveStdOut($"EntryPointFilePath: {filePath}");
}
}
Loading