Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overwrite trx when file name is explicitly provided #4654

Merged
merged 6 commits into from
Jan 15, 2025
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
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema

<!--
Microsoft ResX Schema
Version 2.0

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>

There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -138,6 +138,9 @@
<data name="TrxComparerToolOtherFileOptionDescription" xml:space="preserve">
<value>The TRX file to compare with the baseline</value>
</data>
<data name="TrxFileExistsAndWillBeOverwritten" xml:space="preserve">
<value>Warning: Trx file '{0}' already exists and will be overwritten.</value>
</data>
<data name="TrxReportArtifactDescription" xml:space="preserve">
<value>Test session</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Soubor TRX, který se má porovnat se standardními hodnotami</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Relace testu</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Die TRX-Datei, die mit der Baseline verglichen werden soll</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Testsitzung</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Archivo TRX que se va a comparar con la línea base</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Sesión de prueba</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Fichier TRX à comparer à la ligne de base</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Session de test</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">File TRX da confrontare con la baseline</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Sessione di test</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">ベースラインと比較する TRX ファイル</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">テスト セッション</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">기준과 비교할 TRX 파일입니다.</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">테스트 세션</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Plik TRX do porównania z punktem odniesienia</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Sesja testowa</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">O arquivo TRX a ser comparado com a linha de base</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Sessão de teste</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">TRX-файл для сравнения с базовыми показателями</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Тестовый сеанс</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">Taban çizgisiyle karşılaştırılacak TRX dosyası</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">Test oturumu</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">要与基线进行比较的 TRX 文件</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">测试会话</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
<target state="translated">要與基準比較的 TRX 檔案</target>
<note />
</trans-unit>
<trans-unit id="TrxFileExistsAndWillBeOverwritten">
<source>Warning: Trx file '{0}' already exists and will be overwritten.</source>
<target state="new">Warning: Trx file '{0}' already exists and will be overwritten.</target>
<note />
</trans-unit>
<trans-unit id="TrxReportArtifactDescription">
<source>Test session</source>
<target state="translated">測試工作階段</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,11 @@ public async Task OnTestSessionFinishingAsync(SessionUid sessionUid, Cancellatio
TrxReportEngine trxReportGeneratorEngine = new(_testApplicationModuleInfo, _environment, _commandLineOptionsService, _configuration,
_clock, _tests.ToArray(), _failedTestsCount, _passedTestsCount, _notExecutedTestsCount, _timeoutTestsCount, _artifactsByExtension, _artifactsByTestNode,
_adapterSupportTrxCapability, _testFramework, _testStartTime.Value, exitCode, cancellationToken);
string reportFileName = await trxReportGeneratorEngine.GenerateReportAsync();
(string reportFileName, string? warning) = await trxReportGeneratorEngine.GenerateReportAsync();
if (warning is not null)
{
await _outputDisplay.DisplayAsync(this, new WarningMessageOutputDeviceData(warning));
}

if (
// TestController is not used when we run in server mode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Testing.Platform.Configurations;
using Microsoft.Testing.Platform.Extensions;
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Extensions.OutputDevice;
using Microsoft.Testing.Platform.Extensions.TestFramework;
using Microsoft.Testing.Platform.Extensions.TestHost;
using Microsoft.Testing.Platform.Extensions.TestHostControllers;
Expand All @@ -16,6 +17,7 @@
using Microsoft.Testing.Platform.IPC.Serializers;
using Microsoft.Testing.Platform.Logging;
using Microsoft.Testing.Platform.Messages;
using Microsoft.Testing.Platform.OutputDevice;
using Microsoft.Testing.Platform.Services;
using Microsoft.Testing.Platform.TestHost;

Expand All @@ -25,6 +27,7 @@ internal sealed class TrxProcessLifetimeHandler :
ITestHostProcessLifetimeHandler,
IDataConsumer,
IDataProducer,
IOutputDeviceDataProducer,
#if NETCOREAPP
IAsyncDisposable
#else
Expand All @@ -38,6 +41,7 @@ internal sealed class TrxProcessLifetimeHandler :
private readonly IConfiguration _configuration;
private readonly IClock _clock;
private readonly ITask _task;
private readonly IOutputDevice _outputDevice;
private readonly ILogger<TrxProcessLifetimeHandler> _logger;
private readonly PipeNameDescription _pipeNameDescription;
private readonly Dictionary<IDataProducer, List<FileArtifact>> _fileArtifacts = new();
Expand All @@ -57,6 +61,7 @@ public TrxProcessLifetimeHandler(
IConfiguration configuration,
IClock clock,
ITask task,
IOutputDevice outputDevice,
PipeNameDescription pipeNameDescription)
{
_commandLineOptions = commandLineOptions;
Expand All @@ -66,6 +71,7 @@ public TrxProcessLifetimeHandler(
_configuration = configuration;
_clock = clock;
_task = task;
_outputDevice = outputDevice;
_pipeNameDescription = pipeNameDescription;
_logger = loggerFactory.CreateLogger<TrxProcessLifetimeHandler>();
_startTime = _clock.UtcNow;
Expand Down Expand Up @@ -165,12 +171,18 @@ public async Task OnTestHostProcessExitedAsync(ITestHostProcessInformation testH
testHostProcessInformation.ExitCode,
cancellation);

(string fileName, string? warning) = await trxReportGeneratorEngine.GenerateReportAsync(
isTestHostCrashed: true,
testHostCrashInfo: $"Test host process pid: {testHostProcessInformation.PID} crashed.");
if (warning is not null)
{
await _outputDevice.DisplayAsync(this, new WarningMessageOutputDeviceData(warning));
}

await _messageBus.PublishAsync(
this,
new FileArtifact(
new FileInfo(await trxReportGeneratorEngine.GenerateReportAsync(
isTestHostCrashed: true,
testHostCrashInfo: $"Test host process pid: {testHostProcessInformation.PID} crashed.")),
new FileInfo(fileName),
ExtensionResources.TrxReportArtifactDisplayName,
ExtensionResources.TrxReportArtifactDescription));
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#endif
using System.Security.Cryptography;

using Microsoft.Testing.Extensions.TestReports.Resources;
using Microsoft.Testing.Platform.CommandLine;
using Microsoft.Testing.Platform.Configurations;
using Microsoft.Testing.Platform.Extensions;
Expand Down Expand Up @@ -142,7 +143,7 @@ public TrxReportEngine(IFileSystem fileSystem, ITestApplicationModuleInfo testAp
_isCopyingFileAllowed = isCopyingFileAllowed;
}

public async Task<string> GenerateReportAsync(string testHostCrashInfo = "", bool isTestHostCrashed = false)
public async Task<(string FileName, string? Warning)> GenerateReportAsync(string testHostCrashInfo = "", bool isTestHostCrashed = false)
=> await RetryWhenIOExceptionAsync(async () =>
{
string testAppModule = _testApplicationModuleInfo.GetCurrentTestApplicationFullPath();
Expand All @@ -158,9 +159,19 @@ public async Task<string> GenerateReportAsync(string testHostCrashInfo = "", boo

// If the user added the trxFileName the runDeploymentRoot would stay the same, We think it's a bug but I found that same behavior on vstest
string runDeploymentRoot = AddTestSettings(testRun, testRunName);
string trxFileName = _commandLineOptionsService.TryGetOptionArgumentList(TrxReportGeneratorCommandLine.TrxReportFileNameOptionName, out string[]? fileName)
? ReplaceInvalidFileNameChars(fileName[0])
: $"{runDeploymentRoot}.trx";
bool isFileNameExplicitlyProvided;
string trxFileName;
if (_commandLineOptionsService.TryGetOptionArgumentList(TrxReportGeneratorCommandLine.TrxReportFileNameOptionName, out string[]? fileName))
{
trxFileName = ReplaceInvalidFileNameChars(fileName[0]);
isFileNameExplicitlyProvided = true;
}
else
{
trxFileName = $"{runDeploymentRoot}.trx";
isFileNameExplicitlyProvided = false;
}

AddResults(testAppModule, testRun, out XElement testDefinitions, out XElement testEntries, out string uncategorizedTestId, out string resultSummaryOutcome);
testRun.Add(testDefinitions);
testRun.Add(testEntries);
Expand Down Expand Up @@ -192,12 +203,14 @@ public async Task<string> GenerateReportAsync(string testHostCrashInfo = "", boo

// Note that we need to dispose the IFileStream, not the inner stream.
// IFileStream implementations will be responsible to dispose their inner stream.
using IFileStream stream = _fileSystem.NewFileStream(finalFileName, FileMode.CreateNew);
using IFileStream stream = _fileSystem.NewFileStream(finalFileName, isFileNameExplicitlyProvided ? FileMode.Create : FileMode.CreateNew);
await document.SaveAsync(stream.Stream, SaveOptions.None, _cancellationToken);
return finalFileName;
return isFileNameExplicitlyProvided && _fileSystem.Exists(finalFileName)
? (finalFileName, string.Format(CultureInfo.InvariantCulture, ExtensionResources.TrxFileExistsAndWillBeOverwritten, finalFileName))
: (finalFileName, null);
});

private async Task<string> RetryWhenIOExceptionAsync(Func<Task<string>> func)
private async Task<(string FileName, string? Warning)> RetryWhenIOExceptionAsync(Func<Task<(string FileName, string? Warning)>> func)
{
DateTimeOffset firstTryTime = _clock.UtcNow;
bool throwIOException = false;
Expand All @@ -216,8 +229,8 @@ private async Task<string> RetryWhenIOExceptionAsync(Func<Task<string>> func)
}
}

// We try for 30 seconds to create a file with a unique name.
if (_clock.UtcNow - firstTryTime > TimeSpan.FromSeconds(30))
// We try for 5 seconds to create a file with a unique name.
if (_clock.UtcNow - firstTryTime > TimeSpan.FromSeconds(5))
{
throwIOException = true;
}
Expand Down
Loading
Loading