From 3f7ddc091184b85a2f502a7f0c1afa654076f0c5 Mon Sep 17 00:00:00 2001 From: Daniel Svensson Date: Wed, 13 Dec 2023 10:55:34 +0100 Subject: [PATCH] Run AspNetCore E2E tests with NET8 on server (#463) .NET8 * Build with dotnet8 sdk * Run AspNetCore E2E tests with .NET8 on server * Run AspNetCore tests on .NET8 Test improvements * improve test failure message from GetReferenceAssemblies * Verify AspNetCore webserver is started before executing e2e tests * Fix invalid handle from CrossProcessLoggingTests when debugger is attached Build improvements * Set MSBUILDDEBUGPATH to allow troubleshooting of build failures * Stop installing dotnet (UseDotNet) for slightly faster build * remove appveyor file * Use msbuild directly in codeql * enable test diagnostics --- .github/workflows/codeql.yml | 7 ++- appveyor.yml | 20 ------- azure-pipelines.yml | 52 +++++++++++-------- ...RiaServices.Hosting.AspNetCore.Test.csproj | 2 +- .../Framework/Logging/CrossProcessLogging.cs | 9 ++++ .../Test/Logging/CrossProcessLoggingTests.cs | 4 +- .../Test/MsBuildHelper.cs | 11 ++-- src/RiaServices.sln | 7 ++- .../AspNetCoreWebsite.csproj | 2 +- .../Main.cs | 40 +++++++++----- ...iaservices.EndToEnd.AspNetCore.Test.csproj | 2 +- .../OperationAwaiter.cs | 6 +++ src/global.json | 2 +- src/test.runsettings | 12 +++-- 14 files changed, 100 insertions(+), 76 deletions(-) delete mode 100644 appveyor.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e7c7e28a6..610f3f296 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,8 +36,11 @@ jobs: languages: ${{ matrix.language }} queries: +security-and-quality - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.1 + + - name: build + run: msbuild src\RiaServices.sln -restore /p:Configuration=Release -v:minimal -m - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index efdebb674..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 1.0.{build} -image: Visual Studio 2017 -configuration: -- Release -platform: Any CPU -init: -- cmd: git lfs uninstall -before_build: -- ps: >- - nuget restore src\RiaServices.sln -build: - project: src\RiaServices.sln - parallel: true - verbosity: minimal -artifacts: -- path: 'NuGet\bin\*.nupkg' -before_test: -- ps: >- - .\Setup-TestDatabases.ps1 -UseSqlCmd -test: off diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 574b746cd..877d44f4d 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,22 +5,31 @@ variables: BuildConfiguration: 'release' BuildPlatform: 'any cpu' Solution: 'src\RiaServices.sln' +# Msbuild might create logs in the following directory in case some of the "tool" tests fail + MSBUILDDEBUGPATH: $(Build.ArtifactStagingDirectory) # Define the following variable for the build pipeline in order to enable sonarcloud analysis # sonarcloud-endpoint: 'sonarcloud.io' steps: -# install dotnet 6 sdk so we can run tests against them -- task: UseDotNet@2 - inputs: - packageType: 'sdk' - version: '6.0.x' - -# install dotet 7 sdk to allow compilation target -- task: UseDotNet@2 - inputs: - packageType: 'sdk' - version: '7.0.x' +# Uncomment below to install dotnet runtime and SDK if they stop beeing preinstalled +## install dotnet 6 +#- task: UseDotNet@2 +# inputs: +# packageType: 'runtime' +# version: '6.0.x' + +## install dotnet 7 +#- task: UseDotNet@2 +# inputs: +# packageType: 'runtime' +# version: '7.0.x' + +## install dotnet 8 sdk +#- task: UseDotNet@2 +# inputs: +# packageType: 'sdk' +# version: '8.0.x' - task: NuGetToolInstaller@1 inputs: @@ -61,7 +70,8 @@ steps: platform: '$(BuildPlatform)' configuration: '$(BuildConfiguration)' maximumCpuCount: true - + +# Load test databases and setup msbuild debug path so it becomes part of artifacts - powershell: | sqllocaldb start MSSQLLocalDB if (-not $?) { write-error "failed to start MSSQLLocalDB" } @@ -86,8 +96,9 @@ steps: codeCoverageEnabled: true platform: '$(BuildPlatform)' configuration: '$(BuildConfiguration)' - diagnosticsEnabled: false - timeoutInMinutes: 15 +# diagnosticsEnabled: false + timeoutInMinutes: 25 + continueOnError: true - task: VSTest@2 displayName: 'Run tests - net6' @@ -99,15 +110,13 @@ steps: !**\obj\** runOnlyImpactedTests: false - # Needed to hardcode path to test adapters for NET48 tests - # pathtoCustomTestAdapters: '$(Build.SourcesDirectory)\src\OpenRiaServices.Server.UnitTesting\Test\bin\$(BuildConfiguration)\net6.0\' runInParallel: true - # runSettingsFile: 'src\test.runsettings' + runSettingsFile: 'src\test.runsettings' codeCoverageEnabled: true platform: '$(BuildPlatform)' configuration: '$(BuildConfiguration)' - diagnosticsEnabled: false - timeoutInMinutes: 15 +# diagnosticsEnabled: true + timeoutInMinutes: 25 - task: SonarCloudAnalyze@1 displayName: 'Run Code Analysis' @@ -142,8 +151,9 @@ steps: inputs: SourceFolder: '$(Agent.TempDirectory)' Contents: | - **\*.dmp - TargetFolder: '$(build.artifactstagingdirectory)' + TestResults/*/* + **/*.diag + TargetFolder: '$(build.artifactstagingdirectory)/vstest' condition: succeededOrFailed() - task: PublishBuildArtifacts@1 diff --git a/src/OpenRiaServices.Hosting.AspNetCore/Test/OpenRiaServices.Hosting.AspNetCore.Test/OpenRiaServices.Hosting.AspNetCore.Test.csproj b/src/OpenRiaServices.Hosting.AspNetCore/Test/OpenRiaServices.Hosting.AspNetCore.Test/OpenRiaServices.Hosting.AspNetCore.Test.csproj index d5c705111..9ad67a3d3 100644 --- a/src/OpenRiaServices.Hosting.AspNetCore/Test/OpenRiaServices.Hosting.AspNetCore.Test/OpenRiaServices.Hosting.AspNetCore.Test.csproj +++ b/src/OpenRiaServices.Hosting.AspNetCore/Test/OpenRiaServices.Hosting.AspNetCore.Test/OpenRiaServices.Hosting.AspNetCore.Test.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 OpenRiaServices.Hosting.AspNetCore 1.0.0.0 diff --git a/src/OpenRiaServices.Tools/Framework/Logging/CrossProcessLogging.cs b/src/OpenRiaServices.Tools/Framework/Logging/CrossProcessLogging.cs index 602145a0f..296720fde 100644 --- a/src/OpenRiaServices.Tools/Framework/Logging/CrossProcessLogging.cs +++ b/src/OpenRiaServices.Tools/Framework/Logging/CrossProcessLogging.cs @@ -56,6 +56,7 @@ using System.IO.Pipes; using System.Text; using System.Threading; +using Microsoft.Win32.SafeHandles; namespace OpenRiaServices.Tools.Logging; @@ -78,6 +79,12 @@ public CrossProcessLoggingWriter(string pipeName) _binaryWriter = new BinaryWriter(new BufferedStream(pipe), Encoding.Unicode); } + public CrossProcessLoggingWriter(Microsoft.Win32.SafeHandles.SafePipeHandle pipeHandle) + { + var pipe = new AnonymousPipeClientStream(PipeDirection.Out, pipeHandle); + _binaryWriter = new BinaryWriter(new BufferedStream(pipe), Encoding.Unicode); + } + public bool HasLoggedErrors { get; private set; } void ILoggingService.LogError(string message, string subcategory, string errorCode, string helpKeyword, string file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber) @@ -168,6 +175,8 @@ public CrossProcessLoggingServer() public string PipeName { get; } + public SafePipeHandle ClientSafePipeHandle => _pipe.ClientSafePipeHandle; + /// /// Read logs and forwards them to . /// any exception will catched and logged diff --git a/src/OpenRiaServices.Tools/Test/Logging/CrossProcessLoggingTests.cs b/src/OpenRiaServices.Tools/Test/Logging/CrossProcessLoggingTests.cs index cd9b6139f..0809d0e5b 100644 --- a/src/OpenRiaServices.Tools/Test/Logging/CrossProcessLoggingTests.cs +++ b/src/OpenRiaServices.Tools/Test/Logging/CrossProcessLoggingTests.cs @@ -14,7 +14,7 @@ public class CrossProcessLoggingTests public void LogsAreForwarded() { using var server = new CrossProcessLoggingServer(); - using (var client = new CrossProcessLoggingWriter(server.PipeName)) + using (var client = new CrossProcessLoggingWriter(server.ClientSafePipeHandle)) { var log = (ILoggingService)client; log.LogMessage("Message"); @@ -73,7 +73,7 @@ public void ExceptionsAreForwarded() ex = e; } - using (var client = new CrossProcessLoggingWriter(server.PipeName)) + using (var client = new CrossProcessLoggingWriter(server.ClientSafePipeHandle)) { var log = (ILoggingService)client; log.LogException(ex); diff --git a/src/OpenRiaServices.Tools/Test/MsBuildHelper.cs b/src/OpenRiaServices.Tools/Test/MsBuildHelper.cs index c917e059d..0efe25cd2 100644 --- a/src/OpenRiaServices.Tools/Test/MsBuildHelper.cs +++ b/src/OpenRiaServices.Tools/Test/MsBuildHelper.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.Versioning; using Microsoft.Build.Evaluation; using Microsoft.Build.Execution; using Microsoft.Build.Framework; @@ -54,12 +52,11 @@ private static void GetReferenceAssemblies(string projectPath, IList ass //"AssignProjectConfiguration" var results = project.Build(new string[] { "ResolveAssemblyReferences" }, new Microsoft.Build.Framework.ILogger[] { log }); - Assert.AreEqual(null, results.Exception, "Build should not have exception result"); // Do early assert on log in case there was a task failure - if(results.OverallResult != BuildResultCode.Success) - Assert.AreEqual(string.Empty, string.Join("\n", log.Errors), "ResolveAssemblyReferences failed, se log"); - Assert.AreEqual(BuildResultCode.Success, results.OverallResult, "ResolveAssemblyReferences failed"); - Assert.AreEqual(string.Empty, string.Join("\n", log.Errors), "Task was successful, but there were errors logged"); + if (results.OverallResult != BuildResultCode.Success || results.Exception is not null || log.Errors.Any()) + { + Assert.Fail($"ResolveAssemblyReferences failed.\n Status {BuildResultCode.Success}.\n\nLog:\n {string.Join("\n", log.Errors)}\n\nException: {results.Exception}"); + } if (results.ResultsByTarget.TryGetValue("ResolveAssemblyReferences", out TargetResult resolveAssemblyReferences)) { diff --git a/src/RiaServices.sln b/src/RiaServices.sln index 3b9ef0237..10f1e0372 100644 --- a/src/RiaServices.sln +++ b/src/RiaServices.sln @@ -19,7 +19,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig ..\.gitignore = ..\.gitignore - ..\appveyor.yml = ..\appveyor.yml ..\azure-pipelines.yml = ..\azure-pipelines.yml ..\Changelog.md = ..\Changelog.md Directory.Build.props = Directory.Build.props @@ -150,13 +149,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetCoreWebsite", "Test\A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRiaServices.Hosting.AspNetCore.Test", "OpenRiaServices.Hosting.AspNetCore\Test\OpenRiaServices.Hosting.AspNetCore.Test\OpenRiaServices.Hosting.AspNetCore.Test.csproj", "{A9C063D1-4451-47C9-AACE-908FFC8C9F35}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRiaServices.Tools.CodeGenTask", "OpenRiaServices.Tools.CodeGenTask\OpenRiaServices.Tools.CodeGenTask.csproj", "{E0153323-9B1E-47EA-ACAD-E7A1E765001C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRiaServices.Tools.CodeGenTask", "OpenRiaServices.Tools.CodeGenTask\OpenRiaServices.Tools.CodeGenTask.csproj", "{E0153323-9B1E-47EA-ACAD-E7A1E765001C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EndToEnd", "EndToEnd", "{27DB096E-8794-4B9A-B3D0-AF74926DF9FD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRiaservices.EndToEnd.Wcf.Test", "Test\OpenRiaservices.EndToEnd.Wcf.Test\OpenRiaservices.EndToEnd.Wcf.Test.csproj", "{9428260A-EA94-430D-9A1A-CB9830B9E8EE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRiaservices.EndToEnd.Wcf.Test", "Test\OpenRiaservices.EndToEnd.Wcf.Test\OpenRiaservices.EndToEnd.Wcf.Test.csproj", "{9428260A-EA94-430D-9A1A-CB9830B9E8EE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRiaservices.EndToEnd.AspNetCore.Test", "Test\OpenRiaservices.EndToEnd.AspNetCore.Test\OpenRiaservices.EndToEnd.AspNetCore.Test.csproj", "{17F902F4-7254-4FB9-9AF6-B3291B129B45}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenRiaservices.EndToEnd.AspNetCore.Test", "Test\OpenRiaservices.EndToEnd.AspNetCore.Test\OpenRiaservices.EndToEnd.AspNetCore.Test.csproj", "{17F902F4-7254-4FB9-9AF6-B3291B129B45}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Test/AspNetCoreWebsite/AspNetCoreWebsite.csproj b/src/Test/AspNetCoreWebsite/AspNetCoreWebsite.csproj index b0e44748c..58761549b 100644 --- a/src/Test/AspNetCoreWebsite/AspNetCoreWebsite.csproj +++ b/src/Test/AspNetCoreWebsite/AspNetCoreWebsite.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 disable false $(NoWarn);CS0618 diff --git a/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/Main.cs b/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/Main.cs index bc2a421f6..93e847767 100644 --- a/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/Main.cs +++ b/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/Main.cs @@ -7,7 +7,6 @@ using System.Net.Http; using System.Threading; using httpDomainClient::OpenRiaServices.Client.DomainClients; -using OpenRiaServices.Common.Test; using System.Diagnostics; namespace OpenRiaServices.Client.Test @@ -66,17 +65,10 @@ private static void StartWebServer() #else string configuration = "Release"; #endif - -#if NET80 string targetFramework = "net8.0"; -#else - string targetFramework = "net6.0"; -#endif - string webSitePath = Path.GetFullPath(Path.Combine(projectPath, @$"../AspNetCoreWebsite/bin/{configuration}/{targetFramework}/")); - string processPath = webSitePath + ProcessName + ".exe"; - //webSitePath = Path.GetFullPath(Path.Combine(projectPath, @"../AspNetCoreWebsite")); + if (!Directory.Exists(webSitePath)) throw new FileNotFoundException($"Website not found at {webSitePath}"); @@ -86,6 +78,7 @@ private static void StartWebServer() var websites = Process.GetProcessesByName(ProcessName); if (websites.Any()) { + Console.WriteLine("AssemblyInitialize: Webserver process was already started, not starting anything"); // Already running do nothing } else @@ -96,12 +89,35 @@ private static void StartWebServer() startInfo.WorkingDirectory = Path.GetFullPath(Path.Combine(projectPath, @"../AspNetCoreWebsite/")); s_aspNetCoreSite = Process.Start(startInfo); - // TODO: Wait for standard output or similar instead such as makin a successfull (GET "/")) - Thread.Sleep(TimeSpan.FromSeconds(10)); + Console.WriteLine("AssemblyInitialize: Started webserver with PID {0}", s_aspNetCoreSite.Id); + } + + // Wait for a successfull (GET "/") to succeed so we know webserver has started + using HttpClient httpClient = new HttpClient(); + Stopwatch stopwatch = Stopwatch.StartNew(); + do + { + try + { + var res = httpClient.GetAsync("http://localhost:5246/").GetAwaiter().GetResult(); + if (res.IsSuccessStatusCode) + { + Console.WriteLine("AssemblyInitialize: Webserver started"); + return; + } + } + catch (Exception) + { + // Ignore error + } if (s_aspNetCoreSite.HasExited) throw new Exception("Website stopped"); - } + + Thread.Sleep(TimeSpan.FromSeconds(1)); + } while (stopwatch.Elapsed <= TimeSpan.FromMinutes(1)); + + throw new TimeoutException("webserver did not respond to '/' in 1 minute"); } } } diff --git a/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/OpenRiaservices.EndToEnd.AspNetCore.Test.csproj b/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/OpenRiaservices.EndToEnd.AspNetCore.Test.csproj index 29dadcd5e..f98c25f70 100644 --- a/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/OpenRiaservices.EndToEnd.AspNetCore.Test.csproj +++ b/src/Test/OpenRiaservices.EndToEnd.AspNetCore.Test/OpenRiaservices.EndToEnd.AspNetCore.Test.csproj @@ -48,7 +48,7 @@ false All false - TargetFramework=net6.0 + TargetFramework=net8.0 diff --git a/src/Test/OpenRiaservices.EndToEnd.Wcf.Test/OperationAwaiter.cs b/src/Test/OpenRiaservices.EndToEnd.Wcf.Test/OperationAwaiter.cs index c9af12154..43ab11cbd 100644 --- a/src/Test/OpenRiaservices.EndToEnd.Wcf.Test/OperationAwaiter.cs +++ b/src/Test/OpenRiaservices.EndToEnd.Wcf.Test/OperationAwaiter.cs @@ -38,6 +38,12 @@ public void OnCompleted(Action continuation) public void UnsafeOnCompleted(Action continuation) { + if (_operation.IsComplete) + { + continuation(); + return; + } + // Capture syncContext and scheduler from await location var syncContext = SynchronizationContext.Current; TaskScheduler scheduler; diff --git a/src/global.json b/src/global.json index 2458b5b63..cf2164e4e 100644 --- a/src/global.json +++ b/src/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.200", + "version": "8.0.100", "rollForward": "major" } } \ No newline at end of file diff --git a/src/test.runsettings b/src/test.runsettings index 598cfeb88..3ff490790 100644 --- a/src/test.runsettings +++ b/src/test.runsettings @@ -69,19 +69,23 @@ + + + + + + - - - + - +