From f7efb36103165ab9857fd1002963475a30eb2858 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 15:14:44 +0200 Subject: [PATCH 01/12] - WebServerUploadResults option, default true - async WriteResults - use HTTP POST when in available - always single line otherwise --- .../Arguments/WebServerUploadResults.cs | 13 ++++++++++ .../WASI/WasiTestCommandArguments.cs | 1 + .../WASM/IWebServerArguments.cs | 2 ++ .../WASM/WasmTestBrowserCommandArguments.cs | 1 + .../WASM/WasmTestCommandArguments.cs | 1 + .../WASM/WebServerCommandArguments.cs | 3 +++ .../Commands/WebServer.cs | 20 +++++++++++++++ .../ApplicationEntryPoint.cs | 8 +++--- .../TestRunner.cs | 4 +-- .../NUnitTestRunner.cs | 14 ++++++----- .../ThreadlessXunitTestRunner.cs | 22 ++++------------ .../WasmApplicationEntryPoint.cs | 2 +- .../WasmThreadedTestRunner.cs | 4 +-- .../WasmXmlResultWriter.cs | 25 ++++++++++++++++++- .../XUnitTestRunner.cs | 15 +++++------ 15 files changed, 95 insertions(+), 40 deletions(-) create mode 100644 src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Arguments/WebServerUploadResults.cs diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Arguments/WebServerUploadResults.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Arguments/WebServerUploadResults.cs new file mode 100644 index 000000000..1cbef9d41 --- /dev/null +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/Arguments/WebServerUploadResults.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.DotNet.XHarness.CLI.CommandArguments; + +internal class WebServerUploadResults : SwitchArgument +{ + public WebServerUploadResults() + : base("web-server-upload-results", "Enable uploading XML test results", true) + { + } +} diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASI/WasiTestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASI/WasiTestCommandArguments.cs index 441eb954d..8ae98786d 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASI/WasiTestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASI/WasiTestCommandArguments.cs @@ -25,6 +25,7 @@ internal class WasiTestCommandArguments : XHarnessCommandArguments, IWebServerAr public WebServerUseCrossOriginPolicyArguments WebServerUseCrossOriginPolicy { get; } = new(); public WebServerUseDefaultFilesArguments WebServerUseDefaultFiles { get; } = new(); public bool IsWebServerEnabled => WebServerMiddlewarePathsAndTypes.Value.Count > 0; + public WebServerUploadResults WebServerUploadResults { get; } = new(); protected override IEnumerable GetArguments() => new Argument[] { diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/IWebServerArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/IWebServerArguments.cs index b4c672157..c10c49e24 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/IWebServerArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/IWebServerArguments.cs @@ -14,4 +14,6 @@ internal interface IWebServerArguments WebServerUseCorsArguments WebServerUseCors { get; } WebServerUseCrossOriginPolicyArguments WebServerUseCrossOriginPolicy { get; } WebServerUseDefaultFilesArguments WebServerUseDefaultFiles { get; } + WebServerUploadResults WebServerUploadResults { get; } + OutputDirectoryArgument OutputDirectory { get; } } diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs index 25678458e..1d980c118 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestBrowserCommandArguments.cs @@ -38,6 +38,7 @@ internal class WasmTestBrowserCommandArguments : XHarnessCommandArguments, IWebS public WebServerUseCorsArguments WebServerUseCors { get; } = new(); public WebServerUseCrossOriginPolicyArguments WebServerUseCrossOriginPolicy { get; } = new(); public WebServerUseDefaultFilesArguments WebServerUseDefaultFiles { get; } = new(); + public WebServerUploadResults WebServerUploadResults { get; } = new(); public bool IsWebServerEnabled => WebServerMiddlewarePathsAndTypes.Value.Count > 0; protected override IEnumerable GetArguments() => new Argument[] diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs index 44fd3b2b6..20675e172 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WasmTestCommandArguments.cs @@ -30,6 +30,7 @@ internal class WasmTestCommandArguments : XHarnessCommandArguments, IWebServerAr public WebServerUseCorsArguments WebServerUseCors { get; } = new(); public WebServerUseCrossOriginPolicyArguments WebServerUseCrossOriginPolicy { get; } = new(); public WebServerUseDefaultFilesArguments WebServerUseDefaultFiles { get; } = new(); + public WebServerUploadResults WebServerUploadResults { get; } = new(); public bool IsWebServerEnabled => WebServerMiddlewarePathsAndTypes.Value.Count > 0; protected override IEnumerable GetArguments() => new Argument[] diff --git a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WebServerCommandArguments.cs b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WebServerCommandArguments.cs index d4d1d3c18..3b708a07c 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WebServerCommandArguments.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/CommandArguments/WASM/WebServerCommandArguments.cs @@ -18,6 +18,9 @@ internal class WebServerCommandArguments : XHarnessCommandArguments, IWebServerA public WebServerUseCorsArguments WebServerUseCors { get; } = new(); public WebServerUseCrossOriginPolicyArguments WebServerUseCrossOriginPolicy { get; } = new(); public WebServerUseDefaultFilesArguments WebServerUseDefaultFiles { get; } = new(); + public WebServerUploadResults WebServerUploadResults { get; } = new(); + public OutputDirectoryArgument OutputDirectory { get; } = new(); + public bool IsWebServerEnabled => WebServerMiddlewarePathsAndTypes.Value.Count > 0; public TimeoutArgument Timeout { get; } = new(TimeSpan.FromMinutes(15)); diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 3a42365f9..456246bb0 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -21,6 +21,7 @@ using LogLevel = Microsoft.Extensions.Logging.LogLevel; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; +using System.IO; namespace Microsoft.DotNet.XHarness.CLI.Commands; @@ -175,6 +176,19 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor + { + router.MapPost("/test-results", async context => + { + var xmlResultsFilePath = Path.Combine(options.OutputDirectory ?? Directory.CreateTempSubdirectory().FullName, "testResults.xml"); + using var fileStream = new FileStream(xmlResultsFilePath, FileMode.Create); + await context.Request.Body.CopyToAsync(fileStream); + _logger.LogInformation($"Stored {xmlResultsFilePath} results"); + }); + }); + } foreach (var middleware in options.EchoServerMiddlewares) { @@ -192,6 +206,8 @@ internal class TestWebServerOptions public bool UseHttps { get; set; } public bool UseCrossOriginPolicy { get; set; } public bool UseDefaultFiles { get; set; } + public bool WebServerUploadResults { get; set; } + public string? OutputDirectory { get; set; } public string? ContentRoot { get; set; } public void CopyTo(TestWebServerOptions otherOptions) @@ -202,6 +218,8 @@ public void CopyTo(TestWebServerOptions otherOptions) otherOptions.UseHttps = UseHttps; otherOptions.UseCrossOriginPolicy = UseCrossOriginPolicy; otherOptions.UseDefaultFiles = UseDefaultFiles; + otherOptions.WebServerUploadResults = WebServerUploadResults; + otherOptions.OutputDirectory = OutputDirectory; otherOptions.ContentRoot = ContentRoot; } @@ -212,6 +230,8 @@ public static TestWebServerOptions FromArguments(IWebServerArguments arguments) options.UseHttps = arguments.WebServerUseHttps; options.UseCrossOriginPolicy = arguments.WebServerUseCrossOriginPolicy; options.UseDefaultFiles = arguments.WebServerUseDefaultFiles; + options.WebServerUploadResults = arguments.WebServerUploadResults; + options.OutputDirectory = arguments.OutputDirectory; foreach (var middlewareType in arguments.WebServerMiddlewarePathsAndTypes.GetLoadedTypes()) { options.EchoServerMiddlewares.Add(middlewareType); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationEntryPoint.cs index 5b36565ef..ca6ca5fbd 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Common/ApplicationEntryPoint.cs @@ -173,7 +173,7 @@ internal static void ConfigureRunnerFilters(TestRunner runner, ApplicationOption } } - private static void WriteResults(TestRunner runner, ApplicationOptions options, LogWriter logger, TextWriter writer) + private static async Task WriteResults(TestRunner runner, ApplicationOptions options, LogWriter logger, TextWriter writer) { if (options.EnableXml && writer == null) { @@ -182,12 +182,12 @@ private static void WriteResults(TestRunner runner, ApplicationOptions options, if (options.EnableXml) { - runner.WriteResultsToFile(writer, options.XmlVersion); + await runner.WriteResultsToFile(writer, options.XmlVersion); logger.Info("Xml file was written to the provided writer."); } else { - string resultsFilePath = runner.WriteResultsToFile(options.XmlVersion); + string resultsFilePath = await runner.WriteResultsToFile(options.XmlVersion); logger.Info($"XML results can be found in '{resultsFilePath}'"); } } @@ -227,7 +227,7 @@ protected async Task InternalRunAsync(ApplicationOptions options, Te logger.MinimumLogLevel = MinimumLogLevel.Info; var runner = await InternalRunAsync(logger); - WriteResults(runner, options, logger, resultsFile ?? Console.Out); + await WriteResults(runner, options, logger, resultsFile ?? Console.Out); logger.Info($"{Environment.NewLine}=== TEST EXECUTION SUMMARY ==={Environment.NewLine}Tests run: {runner.TotalTests} Passed: {runner.PassedTests} Inconclusive: {runner.InconclusiveTests} Failed: {runner.FailedTests} Ignored: {runner.FilteredTests} Skipped: {runner.SkippedTests}{Environment.NewLine}"); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Common/TestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Common/TestRunner.cs index 7d4ee0ff2..7fbcc8768 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Common/TestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Common/TestRunner.cs @@ -112,8 +112,8 @@ protected TestRunner(LogWriter logger) } public abstract Task Run(IEnumerable testAssemblies); - public abstract string WriteResultsToFile(XmlResultJargon xmlResultJargon); - public abstract void WriteResultsToFile(TextWriter writer, XmlResultJargon jargon); + public abstract Task WriteResultsToFile(XmlResultJargon xmlResultJargon); + public abstract Task WriteResultsToFile(TextWriter writer, XmlResultJargon jargon); public abstract void SkipTests(IEnumerable tests); public abstract void SkipCategories(IEnumerable categories); public abstract void SkipMethod(string method, bool isExcluded); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs index b9d8d1920..c79d68b67 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.NUnit/NUnitTestRunner.cs @@ -158,32 +158,34 @@ private bool ReportFilteredAssembly(TestAssemblyInfo assemblyInfo, bool include) return include; } - public override string WriteResultsToFile(XmlResultJargon jargon) + public override Task WriteResultsToFile(XmlResultJargon jargon) { if (_results == null) { - return string.Empty; + return Task.FromResult(string.Empty); } string ret = GetResultsFilePath(); if (string.IsNullOrEmpty(ret)) { - return string.Empty; + return Task.FromResult(string.Empty); } jargon.GetWriter().WriteResultFile(_results, ret); - return ret; + return Task.FromResult(ret); } - public override void WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) + public override Task WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) { if (_results == null) { - return; + return Task.CompletedTask; } jargon.GetWriter().WriteResultFile(_results, writer); + + return Task.CompletedTask; } public override void SkipTests(IEnumerable tests) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs index dd9cf08e1..02227905f 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs @@ -19,16 +19,14 @@ namespace Microsoft.DotNet.XHarness.TestRunners.Xunit; internal class ThreadlessXunitTestRunner : XunitTestRunnerBase { - public ThreadlessXunitTestRunner(LogWriter logger, bool oneLineResults = false) : base(logger) + public ThreadlessXunitTestRunner(LogWriter logger) : base(logger) { - _oneLineResults = oneLineResults; ShowFailureInfos = false; } protected override string ResultsFileName { get => string.Empty; set => throw new InvalidOperationException("This runner outputs its results to stdout."); } private readonly XElement _assembliesElement = new XElement("assemblies"); - private readonly bool _oneLineResults; public override async Task Run(IEnumerable testAssemblies) { @@ -110,26 +108,16 @@ private ExecutionSummary Combine(ExecutionSummary aggregateSummary, ExecutionSum }; } - public override string WriteResultsToFile(XmlResultJargon xmlResultJargon) + public override async Task WriteResultsToFile(XmlResultJargon xmlResultJargon) { Debug.Assert(xmlResultJargon == XmlResultJargon.xUnit); - WriteResultsToFile(Console.Out, xmlResultJargon); + await WriteResultsToFile(Console.Out, xmlResultJargon); return ""; } - public override void WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) + public override async Task WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) { - if (_oneLineResults) - { - WasmXmlResultWriter.WriteOnSingleLine(_assembliesElement); - } - else - { - writer.WriteLine($"STARTRESULTXML"); - _assembliesElement.Save(writer); - writer.WriteLine(); - writer.WriteLine($"ENDRESULTXML"); - } + await WasmXmlResultWriter.WriteResultsToFile(_assembliesElement); } } diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs index aa28cf2af..31751b807 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmApplicationEntryPoint.cs @@ -28,7 +28,7 @@ public abstract class WasmApplicationEntryPoint : WasmApplicationEntryPointBase protected override TestRunner GetTestRunner(LogWriter logWriter) { XunitTestRunnerBase runner = IsThreadless - ? new ThreadlessXunitTestRunner(logWriter, true) + ? new ThreadlessXunitTestRunner(logWriter) : new WasmThreadedTestRunner(logWriter) { MaxParallelThreads = MaxParallelThreads }; ConfigureRunnerFilters(runner, ApplicationOptions.Current); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmThreadedTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmThreadedTestRunner.cs index 77ac96453..cfddb05fb 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmThreadedTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmThreadedTestRunner.cs @@ -31,6 +31,6 @@ public override Task Run(IEnumerable testAssemblies) return base.Run(testAssemblies); } - public override void WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) - => WasmXmlResultWriter.WriteOnSingleLine(AssembliesElement); + public override Task WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) + => WasmXmlResultWriter.WriteResultsToFile(AssembliesElement); } diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs index cfef8d454..8976d444b 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs @@ -4,6 +4,10 @@ using System; using System.IO; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Runtime.InteropServices.JavaScript; +using System.Threading.Tasks; using System.Xml.Linq; #nullable enable @@ -12,10 +16,29 @@ namespace Microsoft.DotNet.XHarness.TestRunners.Xunit; internal class WasmXmlResultWriter { - public static void WriteOnSingleLine(XElement assembliesElement) + public async static Task WriteResultsToFile(XElement assembliesElement) { using var ms = new MemoryStream(); assembliesElement.Save(ms); + + if (OperatingSystem.IsBrowser() && JSHost.GlobalThis.HasProperty("fetch")) + { + // globalThis.location.origin + var originURL = JSHost.GlobalThis.GetPropertyAsJSObject("location")!.GetPropertyAsString("origin"); + using var req = new HttpRequestMessage(HttpMethod.Post, originURL + "/test-results"); + req.Content = new StreamContent(ms); + req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml"); + req.Content.Headers.ContentLength = ms.Length; + + using var httpClient = new HttpClient(); + using var response = await httpClient.SendAsync(req); + if (response.IsSuccessStatusCode) + { + Console.WriteLine($"Finished uploading {ms.Length} bytes of RESULTXML"); + return; + } + } + ms.TryGetBuffer(out var bytes); var base64 = Convert.ToBase64String(bytes, Base64FormattingOptions.None); Console.WriteLine($"STARTRESULTXML {bytes.Count} {base64} ENDRESULTXML"); diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs index 187e62671..84a3ec07b 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/XUnitTestRunner.cs @@ -901,11 +901,11 @@ public override async Task Run(IEnumerable testAssemblies) TotalTests += FilteredTests; // ensure that we do have in the total run the excluded ones. } - public override string WriteResultsToFile(XmlResultJargon jargon) + public override Task WriteResultsToFile(XmlResultJargon jargon) { if (_assembliesElement == null) { - return string.Empty; + return Task.FromResult(string.Empty); } // remove all the empty nodes _assembliesElement.Descendants().Where(e => e.Name == "collection" && !e.Descendants().Any()).Remove(); @@ -926,15 +926,15 @@ public override string WriteResultsToFile(XmlResultJargon jargon) _assembliesElement.Save(xmlWriter); break; } - } - - return outputFilePath; + } + + return Task.FromResult(outputFilePath); } - public override void WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) + public override Task WriteResultsToFile(TextWriter writer, XmlResultJargon jargon) { if (_assembliesElement == null) { - return; + return Task.CompletedTask; } // remove all the empty nodes _assembliesElement.Descendants().Where(e => e.Name == "collection" && !e.Descendants().Any()).Remove(); @@ -969,6 +969,7 @@ public override void WriteResultsToFile(TextWriter writer, XmlResultJargon jargo break; } } + return Task.CompletedTask; } private void Transform_Results(string xsltResourceName, XElement element, XmlWriter writer) From e9545f97de80d376feb60225def3b62d47174464 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 15:19:04 +0200 Subject: [PATCH 02/12] fix --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 456246bb0..2dabbfc60 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -184,7 +184,7 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor Date: Mon, 31 Mar 2025 15:21:50 +0200 Subject: [PATCH 03/12] fix --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 2dabbfc60..3e3893698 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -184,7 +184,8 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor Date: Mon, 31 Mar 2025 15:36:10 +0200 Subject: [PATCH 04/12] fix --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 2 +- .../WasmXmlResultWriter.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 3e3893698..2fea2ebb0 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -186,7 +186,7 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor Date: Mon, 31 Mar 2025 16:19:53 +0200 Subject: [PATCH 05/12] Update src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Köplinger --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 2fea2ebb0..bc7f11c24 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -183,9 +183,8 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor { var xmlResultsFilePath = Path.Combine(options.OutputDirectory ?? Directory.CreateTempSubdirectory().FullName, "testResults.xml"); - using var fileStream = new FileStream(xmlResultsFilePath, FileMode.Create); - await context.Request.Body.CopyToAsync(fileStream); - await fileStream.FlushAsync(); + await using var fileStream = File.Create(xmlResultsFilePath); + await request.BodyReader.CopyToAsync(fileStream); _logger.LogInformation($"Stored {xmlResultsFilePath} results {fileStream.Position} bytes"); }); }); From 0d4336b471807d42147174f3e584024be0af2c5f Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 16:20:55 +0200 Subject: [PATCH 06/12] feedback --- .../WasmXmlResultWriter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs index 408135ab8..52c48636f 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs @@ -39,6 +39,7 @@ public async static Task WriteResultsToFile(XElement assembliesElement) Console.WriteLine($"Finished uploading {ms.Length} bytes of RESULTXML"); return; } + // otherwise fall back to the console output } ms.TryGetBuffer(out var bytes); From 224b163f2ab14c676a18c7abad68b6bed94f70d5 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 16:22:31 +0200 Subject: [PATCH 07/12] fix --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index bc7f11c24..8202110f9 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -184,7 +184,7 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor Date: Mon, 31 Mar 2025 16:26:06 +0200 Subject: [PATCH 08/12] make sure this is browser --- .../WasmXmlResultWriter.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs index 52c48636f..76e8889d8 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs @@ -21,7 +21,10 @@ public async static Task WriteResultsToFile(XElement assembliesElement) using var ms = new MemoryStream(); assembliesElement.Save(ms); - if (OperatingSystem.IsBrowser() && JSHost.GlobalThis.HasProperty("fetch")) + if (OperatingSystem.IsBrowser() + && JSHost.GlobalThis.HasProperty("fetch") + && JSHost.GlobalThis.HasProperty("location") + && JSHost.GlobalThis.HasProperty("document")) { ms.Position = 0; From 6fdca965016efedc5b9cde86955b8d88b3ddba25 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 16:44:23 +0200 Subject: [PATCH 09/12] more defensive and dispose JSObject --- .../WasmXmlResultWriter.cs | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs index 76e8889d8..a02587dbc 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs @@ -21,28 +21,38 @@ public async static Task WriteResultsToFile(XElement assembliesElement) using var ms = new MemoryStream(); assembliesElement.Save(ms); - if (OperatingSystem.IsBrowser() - && JSHost.GlobalThis.HasProperty("fetch") - && JSHost.GlobalThis.HasProperty("location") - && JSHost.GlobalThis.HasProperty("document")) + if (OperatingSystem.IsBrowser()) { - ms.Position = 0; - - // globalThis.location.origin - var originURL = JSHost.GlobalThis.GetPropertyAsJSObject("location")!.GetPropertyAsString("origin"); - using var req = new HttpRequestMessage(HttpMethod.Post, originURL + "/test-results"); - req.Content = new StreamContent(ms); - req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml"); - req.Content.Headers.ContentLength = ms.Length; - - using var httpClient = new HttpClient(); - using var response = await httpClient.SendAsync(req); - if (response.IsSuccessStatusCode) + try { - Console.WriteLine($"Finished uploading {ms.Length} bytes of RESULTXML"); - return; + using JSObject globalThis = JSHost.GlobalThis; + if (globalThis.HasProperty("fetch") && JSHost.GlobalThis.HasProperty("location") && JSHost.GlobalThis.HasProperty("document")) + { + ms.Position = 0; + + // globalThis.location.origin + using JSObject location = JSHost.GlobalThis.GetPropertyAsJSObject("location")!; + var originURL = location.GetPropertyAsString("origin"); + + using var req = new HttpRequestMessage(HttpMethod.Post, originURL + "/test-results"); + req.Content = new StreamContent(ms); + req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml"); + req.Content.Headers.ContentLength = ms.Length; + + using var httpClient = new HttpClient(); + using var response = await httpClient.SendAsync(req); + if (response.IsSuccessStatusCode) + { + Console.WriteLine($"Finished uploading {ms.Length} bytes of RESULTXML"); + return; + } + // otherwise fall back to the console output + } + } + catch (Exception) + { + // fall back to the console output } - // otherwise fall back to the console output } ms.TryGetBuffer(out var bytes); From b3c5fd10032806d11390cb2a7fe4b3571bc1d410 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 31 Mar 2025 16:45:39 +0200 Subject: [PATCH 10/12] cleanup --- .../WasmXmlResultWriter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs index a02587dbc..4c4ec793c 100644 --- a/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs +++ b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs @@ -26,12 +26,12 @@ public async static Task WriteResultsToFile(XElement assembliesElement) try { using JSObject globalThis = JSHost.GlobalThis; - if (globalThis.HasProperty("fetch") && JSHost.GlobalThis.HasProperty("location") && JSHost.GlobalThis.HasProperty("document")) + if (globalThis.HasProperty("fetch") && globalThis.HasProperty("location") && globalThis.HasProperty("document")) { ms.Position = 0; // globalThis.location.origin - using JSObject location = JSHost.GlobalThis.GetPropertyAsJSObject("location")!; + using JSObject location = globalThis.GetPropertyAsJSObject("location")!; var originURL = location.GetPropertyAsString("origin"); using var req = new HttpRequestMessage(HttpMethod.Post, originURL + "/test-results"); From 2b8ec93c8ee9291187b73a60b0e9fc1510cce44f Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Mon, 31 Mar 2025 16:52:52 +0200 Subject: [PATCH 11/12] Update src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Köplinger --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index 8202110f9..fc34500d0 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -182,7 +182,8 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor { - var xmlResultsFilePath = Path.Combine(options.OutputDirectory ?? Directory.CreateTempSubdirectory().FullName, "testResults.xml"); + var xmlResultsFilePath = Path.Combine(options.OutputDirectory, "testResults.xml"); + await using var fileStream = File.Create(xmlResultsFilePath); await context.Request.BodyReader.CopyToAsync(fileStream); _logger.LogInformation($"Stored {xmlResultsFilePath} results {fileStream.Position} bytes"); From bdeac6e203dbc3907a435dd3d62a09929c1b63f9 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Mon, 31 Mar 2025 17:07:44 +0200 Subject: [PATCH 12/12] fix --- src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs index fc34500d0..8985f25bd 100644 --- a/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs +++ b/src/Microsoft.DotNet.XHarness.CLI/Commands/WebServer.cs @@ -182,7 +182,7 @@ public void Configure(IApplicationBuilder app, IOptionsMonitor { - var xmlResultsFilePath = Path.Combine(options.OutputDirectory, "testResults.xml"); + var xmlResultsFilePath = Path.Combine(options.OutputDirectory!, "testResults.xml"); await using var fileStream = File.Create(xmlResultsFilePath); await context.Request.BodyReader.CopyToAsync(fileStream);