Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 commandArgs)
{
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 @@ -1225,6 +1225,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 @@ -1308,6 +1313,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 @@ -1394,6 +1404,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 @@ -1449,4 +1464,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