From 18581b83931fe89291df17162ee8814f94dc2296 Mon Sep 17 00:00:00 2001 From: squarebananas <37810292+squarebananas@users.noreply.github.com> Date: Sat, 14 Sep 2024 07:45:52 +0100 Subject: [PATCH 1/6] Additional fixes for SoundEffectInstance.OpenAL panning (#8480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR provides additional fixes on top of #8466 for supporting SoundEffectInstance.OpenAL panning. These are the points I noted while testing/fixing: ### AudioChannels.Mono Sound Sources - During playback of mono sources, it is not possible to pan fully between left & right. - OpenAL only applies 3D positions to mono channel sources. - When fully panning, moving the position in only one axis will not fully stop output on the opposite speaker. - Also the varying distance between the emitter & listener gives the perception of pan control being less uniform. - Through testing, fully panned left/right output is observed when positioning the emitter at +/-60° at constant distance. ### AudioChannels.Stereo Sound Sources - During playback of stereo sources, channels are not mixed correctly. - OpenAL only applies StereoAngles to stereo channel sources. - StereoAngles are applied counter-clockwise. - With StereoAngles set both to 0°, normal left/right stereo output occurs. - Through testing, full left/right output is observed when the StereoAngles are both set at +/-30°. - If the StereoAngles extension is unsupported, stereo sources cannot be panned at all. - As a workaround, the user could manually split each stereo file into 2 mono files and play simultaneously. ### Other Notes - The percentage of cross channel audio mixed for each speaker may change depending on the platform/driver OpenAL implementation. - I found this particularly noticeable with headphones using Realtek audio on Windows where it is never mixed entirely to just one side. This does not occur on XAudio2 with headphones. ### Description of Changes - Determines if source is AudioChannels.Mono or AudioChannels.Stereo and uses 3D emitter positioning or StereoAngles for panning. - Rotates the 3D emitter position between +/- 60° using Vector2.Rotate for constant distance through both axes. - Sets StereoAngles both to the same value (between -30° to 30°) for full left/right panning. - ALHelper.CheckError descriptions have been corrected or changed. ### Results ![AudioPanning2](https://github.com/user-attachments/assets/b8a62e0f-ca92-4e09-9864-be0bb775e280) _Audacity levels for mono/stereo sources panned from -1 to 1 instantly (square) or using a sine wave. A tone was used for the mono tests and a drum loop for the stereo test._ --- .../Audio/SoundEffectInstance.OpenAL.cs | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/MonoGame.Framework/Platform/Audio/SoundEffectInstance.OpenAL.cs b/MonoGame.Framework/Platform/Audio/SoundEffectInstance.OpenAL.cs index db5407f220b..e7f27430e05 100644 --- a/MonoGame.Framework/Platform/Audio/SoundEffectInstance.OpenAL.cs +++ b/MonoGame.Framework/Platform/Audio/SoundEffectInstance.OpenAL.cs @@ -22,6 +22,7 @@ public partial class SoundEffectInstance : IDisposable int pauseCount; float[] panAngles = new float[2]; + AudioChannels sourceChannels; internal readonly object sourceMutex = new object(); @@ -124,7 +125,10 @@ private void PlatformPlay() // Distance Model AL.DistanceModel (ALDistanceModel.InverseDistanceClamped); ALHelper.CheckError("Failed set source distance."); - // Pan + // Pan + AL.GetBuffer(_effect.SoundBuffer.OpenALDataBuffer, ALGetBufferi.Channels, out int channels); + ALHelper.CheckError("Failed to get buffer channels"); + sourceChannels = (channels == 2) ? AudioChannels.Stereo : AudioChannels.Mono; PlatformSetPan (_pan); // Velocity AL.Source (SourceId, ALSource3f.Velocity, 0f, 0f, 0f); @@ -221,16 +225,40 @@ private void PlatformSetPan(float value) if (HasSourceId) { - AL.Source(SourceId, ALSource3f.Position, _pan, 0.0f, -1f); - ALHelper.CheckError("Failed to set source pan."); - if (controller.SupportsStereoAngles) + // Pan value | -1.0 | 0.0 | +1.0 | + // Output | Left | Centered | Right | + // - The proportion of cross channel audio mixed for each speaker may change depending on the + // platform/driver OpenAL implementation + + float maxPanAngle = (float)Math.PI / 3f; + switch (sourceChannels) { - // pan between -60 degrees when fully left (-1) and 60 degrees when fully right (1) - float angle = (float)Math.PI / 6f; - panAngles[0] = (1.0f - _pan) * angle; - panAngles[1]= (1.0f + _pan) * -angle; - AL.alSourcefv(SourceId, ALSourcef.StereoAngles, panAngles); - ALHelper.CheckError("Failed to set source position."); + case AudioChannels.Mono: + // Simulate pan via 3D emitter positioning + // - Rotates the emitter position +/- 60 degrees around the listener while keeping a constant distance + // - OpenAL only applies 3D positions to mono channel sources + Vector2 pannedPosition = Vector2.Rotate(new Vector2(0, -1), _pan * maxPanAngle); + AL.Source(SourceId, ALSource3f.Position, pannedPosition.X, 0.0f, pannedPosition.Y); + ALHelper.CheckError("Failed to set source position."); + break; + + case AudioChannels.Stereo: + // Pan via StereoAngles extension + // - The panAngles array is set according to these angles (shown as degrees counter-clockwise): + // Pan value | -1.0 | 0.0 | +1.0 | + // panAngles[0] (Output L) | +90 | +30 | -30 | + // panAngles[1] (Output R) | +30 | -30 | -90 | + // - OpenAL only applies StereoAngles to stereo channel sources if the extension is available + // - If unsupported no panning can occur as 3D positioning (mono sources only) is also unavailable + if (!controller.SupportsStereoAngles) + return; + float panAngle = _pan * -maxPanAngle; + float centeredOffsetAngle = (float)Math.PI / 6f; + panAngles[0] = panAngle + centeredOffsetAngle; + panAngles[1] = panAngle - centeredOffsetAngle; + AL.alSourcefv(SourceId, ALSourcef.StereoAngles, panAngles); + ALHelper.CheckError("Failed to set source stereo angles."); + break; } } } From 2a6badc56ad89304853b9d320bda8cc76cf8d0a4 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Sat, 14 Sep 2024 10:31:46 +0100 Subject: [PATCH 2/6] Run the Basic ContentBuilder Tests on CI (#8436) We are currently not running ANY tests on CI. Lets correct this by running at least the content building and processor tests on CI. Certain content pipelines tests (Audio & Effects) have been disabled because they fail or hang on CI at this time. Current the tests run in x64 dotnet so that we can pass the TextureCompression tests. This PR #8456 should fix the texture compression issues so we do not need x64 dotnet. The Effect compilation for Linux /Mac needs to happen in wine. But dotnet 8 does not seem to run under wine on CI at this time. So that will need to be looked at. --- .github/workflows/main.yml | 59 ++++++++++++++- .../Assets/Projects/BuildSimpleProject.csproj | 50 ++----------- .../MonoGame.Content.Builder.Task.targets | 7 +- .../MonoGame.Content.Builder/BuildContent.cs | 8 +- .../MonoGame.Tools.Tests/AudioContentTests.cs | 3 + .../BuilderTargetsTest.cs | 73 ++++++++++--------- .../EffectProcessorTests.cs | 3 + .../MonoGame.Tools.Tests/FbxImporterTests.cs | 4 +- .../IntermediateDeserializerTest.cs | 4 +- .../ModelProcessorTests.cs | 2 + .../MonoGame.Tools.Tests.csproj | 7 ++ .../MonoGame.Tools.Tests/Mp3ImporterTests.cs | 3 + .../MonoGame.Tools.Tests/OggImporterTests.cs | 3 + .../TextureImporterTests.cs | 3 + .../MonoGame.Tools.Tests/WavImporterTests.cs | 3 + .../MonoGame.Tools.Tests/WmaImporterTests.cs | 3 + .../BuildFrameworksTasks/BuildAndroidTask.cs | 15 +++- build/BuildToolsTasks/BuildToolTestsTask.cs | 12 +++ build/Tasks.cs | 6 ++ 19 files changed, 175 insertions(+), 93 deletions(-) create mode 100644 build/BuildToolsTasks/BuildToolTestsTask.cs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5f7dfb69f32..62daee63386 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,25 +25,77 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' - name: Disable annotations run: echo "::remove-matcher owner=csc::" + - name: install wine64 on linux + run: | + sudo apt install p7zip-full curl + sudo dpkg --add-architecture i386 + sudo mkdir -pm755 /etc/apt/keyrings + sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources + sudo apt update && sudo apt install --install-recommends winehq-stable + if: runner.os == 'Linux' + + - name: Install Arial Font + run: | + echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | sudo debconf-set-selections + sudo apt install -y ttf-mscorefonts-installer + sudo fc-cache + fc-match Arial + if: runner.os == 'Linux' + + - name: install wine64 on macos + run: | + brew install wine-stable p7zip freeimage freetype + sudo mkdir -p /usr/local/lib + sudo ln -s /opt/homebrew/lib/libfreetype.dylib /usr/local/lib/libfreetype6.dylib + sudo ln -s /opt/homebrew/lib/libfreeimage.dylib /usr/local/lib/libfreeimage.dylib + if: runner.os == 'macOS' + + - name: Setup Wine + run: wget -qO- https://monogame.net/downloads/net8_mgfxc_wine_setup.sh | bash + if: runner.os != 'Windows' + - name: Install required workloads run: | if [ "$RUNNER_OS" == "Linux" ]; then - echo "MICROSOFT SUPPORT ANDROID WORKLOAD ON LINUX PLZZZ!" + dotnet workload install android elif [ "$RUNNER_OS" == "Windows" ]; then dotnet.exe workload install android ios macos else - dotnet workload install android ios macos + dotnet workload install android fi shell: bash - name: Build run: dotnet run --project build/Build.csproj -- --target=Default + - name: Test + run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release + env: + DOTNET_ROOT: ${{github.workspace}}/dotnet64 + MGFXC_WINE_PATH: /home/runner/.winemonogame + CI: true + if: runner.os == 'Linux' + + - name: Test + run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release + env: + DOTNET_ROOT: ${{github.workspace}}/dotnet64 + MGFXC_WINE_PATH: /Users/runner/.winemonogame + CI: true + if: runner.os == 'macOS' + + - name: Test + run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release + env: + CI: true + if: runner.os == 'Windows' + - name: Expose GitHub Runtime uses: crazy-max/ghaction-github-runtime@v3 @@ -88,3 +140,4 @@ jobs: removeArtifacts: true artifacts: "nugets/*.nupkg" token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/Tests/Assets/Projects/BuildSimpleProject.csproj b/Tests/Assets/Projects/BuildSimpleProject.csproj index f01aead9d8d..ead23a2b9a1 100644 --- a/Tests/Assets/Projects/BuildSimpleProject.csproj +++ b/Tests/Assets/Projects/BuildSimpleProject.csproj @@ -1,50 +1,16 @@  - - + + - Debug - AnyCPU - 8.0.30703 - 2.0 - {1A3C19CC-557D-4009-82D6-92B511EA4172} - WinExe - Properties - BuildSimpleProject - BuildSimpleProject - 512 - DesktopGL - v4.5 - - - - true - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - DEBUG;TRACE;LINUX - full - AnyCPU - prompt - false - 4 - - - - bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\ - TRACE;LINUX - true - pdbonly - AnyCPU - prompt - false - 4 + Exe + net8.0 + Major + false + DesktopGL - - - - - - + diff --git a/Tools/MonoGame.Content.Builder.Task/MonoGame.Content.Builder.Task.targets b/Tools/MonoGame.Content.Builder.Task/MonoGame.Content.Builder.Task.targets index b2df319d63b..4c2ab79c492 100644 --- a/Tools/MonoGame.Content.Builder.Task/MonoGame.Content.Builder.Task.targets +++ b/Tools/MonoGame.Content.Builder.Task/MonoGame.Content.Builder.Task.targets @@ -58,7 +58,8 @@ %(MonoGameContentReference.Link) %(MonoGameContentReference.RootDir)%(MonoGameContentReference.Directory) %(MonoGameContentReference.ContentFolder) - %(MonoGameContentReference.Filename) + %(MonoGameContentReference.OutputFolder) + %(MonoGameContentReference.Filename) - + diff --git a/Tools/MonoGame.Content.Builder/BuildContent.cs b/Tools/MonoGame.Content.Builder/BuildContent.cs index dc712a06154..3e19f9c7303 100644 --- a/Tools/MonoGame.Content.Builder/BuildContent.cs +++ b/Tools/MonoGame.Content.Builder/BuildContent.cs @@ -403,16 +403,12 @@ public void Build(out int successCount, out int errorCount) } catch (PipelineException ex) { - Console.Error.WriteLine("{0}: error: {1}", c.SourceFile, ex.Message); - if (ex.InnerException != null) - Console.Error.WriteLine(ex.InnerException.ToString()); + Console.Error.WriteLine("{0}: error: {1}. {2}", c.SourceFile, ex.Message, ex.InnerException != null ? ex.InnerException : string.Empty); ++errorCount; } catch (Exception ex) { - Console.Error.WriteLine("{0}: error: {1}", c.SourceFile, ex.Message); - if (ex.InnerException != null) - Console.Error.WriteLine(ex.InnerException.ToString()); + Console.Error.WriteLine("{0}: error: {1}. {2}", c.SourceFile, ex.Message, ex.InnerException != null ? ex.InnerException : string.Empty); ++errorCount; } } diff --git a/Tools/MonoGame.Tools.Tests/AudioContentTests.cs b/Tools/MonoGame.Tools.Tests/AudioContentTests.cs index b83284bb721..a43b279ca43 100644 --- a/Tools/MonoGame.Tools.Tests/AudioContentTests.cs +++ b/Tools/MonoGame.Tools.Tests/AudioContentTests.cs @@ -11,6 +11,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS && CI + [Ignore("Hanging on Mac in CI?")] +#endif class AudioContentTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/BuilderTargetsTest.cs b/Tools/MonoGame.Tools.Tests/BuilderTargetsTest.cs index 99455e4be0a..990d3c9d61a 100644 --- a/Tools/MonoGame.Tools.Tests/BuilderTargetsTest.cs +++ b/Tools/MonoGame.Tools.Tests/BuilderTargetsTest.cs @@ -8,64 +8,71 @@ namespace MonoGame.Tests.ContentPipeline [TestFixture] public class BuilderTargetsTest { - string[] msBuildFolders = new string[] + string FindTool (string toolName) { - Path.Combine ("MSBuild", "15.0", "Bin", "MSBuild.exe"), - Path.Combine ("MSBuild", "14.0", "Bin", "MSBuild.exe"), - }; - string FindBuildTool(string buildTool) - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT && buildTool == "msbuild") + var dotnetRoot = Environment.GetEnvironmentVariable ("DOTNET_ROOT"); + TestContext.WriteLine ("DOTNET_ROOT=" + dotnetRoot); + if (!string.IsNullOrEmpty (dotnetRoot)) { - var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); - foreach (var path in msBuildFolders) + var dotNetExe = Path.Combine (dotnetRoot, OperatingSystem.IsWindows() ? "dotnet.exe" : "dotnet"); + TestContext.WriteLine ("DOTNET_EXE=" + dotNetExe); + if (File.Exists (dotNetExe)) { - if (File.Exists(Path.Combine(programFiles, path))) - return Path.Combine(programFiles, path); + TestContext.WriteLine ("returning:" + dotNetExe); + return dotNetExe; } } - return buildTool; + TestContext.WriteLine ("returning:" + toolName); + return toolName; } bool RunBuild(string buildTool, string projectFile, params string[] parameters) { var root = Path.GetDirectoryName(typeof(BuilderTargetsTest).Assembly.Location); - var psi = new ProcessStartInfo(FindBuildTool(buildTool)) + var tool = FindTool(buildTool); + var psi = new ProcessStartInfo(tool) { - Arguments = projectFile + " /t:BuildContent " + string.Join(" ", parameters) + " /noconsolelogger \"/flp1:LogFile=build.log;Encoding=UTF-8;Verbosity=Diagnostic\"", + Arguments = $"build {projectFile} -t:IncludeContent {string.Join(" ", parameters)} -tl:off -bl -p:DotnetCommand=\"{tool}\"", WorkingDirectory = root, - UseShellExecute = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true }; + TestContext.WriteLine (psi.FileName + " " + psi.Arguments); using (var process = Process.Start(psi)) { - process.WaitForExit(); + process.OutputDataReceived += (sender, e) => { + if (!string.IsNullOrEmpty(e.Data)) + { + TestContext.WriteLine($"Output: {e.Data}"); + } + }; + + process.ErrorDataReceived += (sender, e) => { + if (!string.IsNullOrEmpty(e.Data)) + { + TestContext.WriteLine($"Error: {e.Data}"); + } + }; + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + if (!process.WaitForExit(60000)) {// wait for 60 seconds + process.Kill (); + } return process.ExitCode == 0; } } - static object[] BuilderTargetsBuildTools = new object[] { - "msbuild", - "xbuild", - }; - [Test] - [TestCaseSource("BuilderTargetsBuildTools")] -#if DESKTOPGL - [Ignore("Fails on Mac build server with xbuild for some reason.")] -#else - [Ignore("This test need to be rewritten to properly test Tools\\MonoGame.Content.Builder instead of the old builder targets.")] -#endif - public void BuildSimpleProject(string buildTool) + public void BuildSimpleProject() { - if (buildTool == "xbuild" && Environment.OSVersion.Platform == PlatformID.Win32NT) - Assert.Ignore("Skipping xbuild tests on windows"); - var root = Path.GetDirectoryName(typeof(BuilderTargetsTest).Assembly.Location); var outputPath = Path.Combine(root, "Assets", "Projects", "Content", "bin"); if (Directory.Exists(outputPath)) Directory.Delete(outputPath, recursive: true); - var result = RunBuild(buildTool, Path.Combine("Assets", "Projects", "BuildSimpleProject.csproj"), new string[] { - "/p:MonoGameContentBuilderExe=" + Path.Combine(root, "MGCB.exe") + var result = RunBuild("dotnet", Path.Combine(root, "Assets", "Projects", "BuildSimpleProject.csproj"), new string[] { + "-p:MGCBCommand=" + Path.Combine(root, "mgcb.dll") }); Assert.AreEqual(true, result, "Content Build should have succeeded."); var contentFont = Path.Combine(outputPath, "DesktopGL", "Content", "ContentFont.xnb"); diff --git a/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs b/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs index 7a4257981e6..bd4e4357caa 100644 --- a/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs +++ b/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs @@ -10,6 +10,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS || LINUX + [Ignore("Does not work on CI yet. need to get wine working.")] +#endif class EffectProcessorTests { class ImporterContext : ContentImporterContext diff --git a/Tools/MonoGame.Tools.Tests/FbxImporterTests.cs b/Tools/MonoGame.Tools.Tests/FbxImporterTests.cs index b803cb65e1b..cb7504a8b8b 100644 --- a/Tools/MonoGame.Tools.Tests/FbxImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/FbxImporterTests.cs @@ -48,9 +48,7 @@ public void Arguments() } [Test] -#if DESKTOPGL - [Ignore("Disabled until latest NVTT is merged on Mac!")] -#endif + [Ignore("Disabled until latest assimp is merged on Mac and Linux or windows!")] public void Dude() { var context = new TestImporterContext("TestObj", "TestBin"); diff --git a/Tools/MonoGame.Tools.Tests/IntermediateDeserializerTest.cs b/Tools/MonoGame.Tools.Tests/IntermediateDeserializerTest.cs index a96124db31a..5aab19a62fd 100644 --- a/Tools/MonoGame.Tools.Tests/IntermediateDeserializerTest.cs +++ b/Tools/MonoGame.Tools.Tests/IntermediateDeserializerTest.cs @@ -581,8 +581,8 @@ public void ChildCollections() } [Test] -#if DESKTOPGL - [Ignore("Fails on Mac build server some reason.")] +#if MACOS && CI + [Ignore("Fails on Mac build server some reason.")] #endif public void Colors() { diff --git a/Tools/MonoGame.Tools.Tests/ModelProcessorTests.cs b/Tools/MonoGame.Tools.Tests/ModelProcessorTests.cs index 0df69481aaf..c219e85586f 100644 --- a/Tools/MonoGame.Tools.Tests/ModelProcessorTests.cs +++ b/Tools/MonoGame.Tools.Tests/ModelProcessorTests.cs @@ -282,6 +282,7 @@ public void DefaultEffectTest() } [Test] + [Ignore ("Not working yet")] /// /// Test to validate a model with missing normals does not throw an exception using the default ModelProcessor. /// @@ -305,6 +306,7 @@ public void MissingNormalsTestDefault() } [Test] + [Ignore ("Not working yet")] /// /// Test to validate a model with missing normals does not throw an exception using a custom ModelProcessor using MeshHelper.CalculateTangentFrames directly. /// diff --git a/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj b/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj index 23b50f97026..d36daf88307 100644 --- a/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj +++ b/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj @@ -9,6 +9,11 @@ false false DESKTOPGL + $(DefineConstants);MACOS + $(DefineConstants);WINDOWS + $(DefineConstants);LINUX + + $(DefineConstants);CI ..\..\Artifacts\Tests\Tools False true @@ -23,6 +28,8 @@ + + diff --git a/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs b/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs index 5f5ba7f2fe3..665988bf001 100644 --- a/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs @@ -9,6 +9,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS && CI + [Ignore("Hanging on Mac in CI?")] +#endif class Mp3ImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/OggImporterTests.cs b/Tools/MonoGame.Tools.Tests/OggImporterTests.cs index ab0df895009..eeecedf9b74 100644 --- a/Tools/MonoGame.Tools.Tests/OggImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/OggImporterTests.cs @@ -9,6 +9,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS && CI + [Ignore("Hanging on Mac in CI?")] +#endif class OggImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs b/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs index f3e49fb6f8d..c7e20d5e0da 100644 --- a/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs @@ -105,6 +105,9 @@ public void ImportTif( ) /// Note that the image was created with Freeimage from a bitmap /// [Test] +#if MACOS || LINUX + [Ignore("Does not work on Unix based systems. We need to get wine working on CI.")] +#endif public void ImportImageWithBadContent( ) { Assert.Throws(typeof(InvalidContentException), ( ) => ImportStandard("Assets/Textures/rgbf.tif", SurfaceFormat.Vector4, 64)); diff --git a/Tools/MonoGame.Tools.Tests/WavImporterTests.cs b/Tools/MonoGame.Tools.Tests/WavImporterTests.cs index fd367c2e2d3..0439e40a0ad 100644 --- a/Tools/MonoGame.Tools.Tests/WavImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/WavImporterTests.cs @@ -9,6 +9,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS && CI + [Ignore("Hanging on Mac in CI")] +#endif class WavImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs b/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs index f04a9807af7..7bca033404f 100644 --- a/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs @@ -9,6 +9,9 @@ namespace MonoGame.Tests.ContentPipeline { +#if MACOS && CI + [Ignore("Hanging on Mac in CI?")] +#endif class WmaImporterTests { [Test] diff --git a/build/BuildFrameworksTasks/BuildAndroidTask.cs b/build/BuildFrameworksTasks/BuildAndroidTask.cs index 70fa840712a..3a1e5784f10 100644 --- a/build/BuildFrameworksTasks/BuildAndroidTask.cs +++ b/build/BuildFrameworksTasks/BuildAndroidTask.cs @@ -7,5 +7,18 @@ public sealed class BuildAndroidTask : FrostingTask public override bool ShouldRun(BuildContext context) => context.IsWorkloadInstalled("android"); public override void Run(BuildContext context) - => context.DotNetPack(context.GetProjectPath(ProjectType.Framework, "Android"), context.DotNetPackSettings); + { + var arguments = new DotNetMSBuildSettings(); + arguments.WithProperty("AndroidSdkDirectory", System.Environment.GetEnvironmentVariable ("ANDROID_HOME")); + arguments.WithProperty("AcceptAndroidSDKLicenses", "true"); + arguments.WithTarget("InstallAndroidDependencies"); + var installSettings = new DotNetBuildSettings + { + MSBuildSettings = arguments, + Verbosity = DotNetVerbosity.Minimal, + Configuration = context.DotNetPackSettings.Configuration, + }; + context.DotNetBuild(context.GetProjectPath(ProjectType.Framework, "Android"), installSettings); + context.DotNetPack(context.GetProjectPath(ProjectType.Framework, "Android"), context.DotNetPackSettings); + } } diff --git a/build/BuildToolsTasks/BuildToolTestsTask.cs b/build/BuildToolsTasks/BuildToolTestsTask.cs new file mode 100644 index 00000000000..15f9c9f23e5 --- /dev/null +++ b/build/BuildToolsTasks/BuildToolTestsTask.cs @@ -0,0 +1,12 @@ + +namespace BuildScripts; + +[TaskName("Build ToolTests")] +[IsDependentOn(typeof(BuildContentPipelineTask))] +public sealed class BuildToolTestsTask : FrostingTask +{ + public override void Run(BuildContext context) + { + context.DotNetBuild(context.GetProjectPath(ProjectType.Tools, "MonoGame.Tools.Tests"), context.DotNetBuildSettings); + } +} \ No newline at end of file diff --git a/build/Tasks.cs b/build/Tasks.cs index fc74aa211a3..214275926c4 100644 --- a/build/Tasks.cs +++ b/build/Tasks.cs @@ -23,10 +23,16 @@ public sealed class BuildToolsTask : FrostingTask { } [IsDependentOn(typeof(BuildVSTemplatesTask))] public sealed class BuildTemplatesTask : FrostingTask { } +[TaskName("Build Tests")] +[IsDependentOn(typeof(BuildToolTestsTask))] +public sealed class BuildTestsTask : FrostingTask { } + + [TaskName("Build All")] [IsDependentOn(typeof(BuildFrameworksTask))] [IsDependentOn(typeof(BuildToolsTask))] [IsDependentOn(typeof(BuildTemplatesTask))] +[IsDependentOn(typeof(BuildTestsTask))] public sealed class BuildAllTask : FrostingTask { } [TaskName("Deploy")] From aff977c769c2a447dc9f699df93a578acfa7975a Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Sat, 14 Sep 2024 10:36:58 +0100 Subject: [PATCH 3/6] Upgrade Android to handle obsolete API's. (#8420) * Upgrade Android to handle obsolete API's. As the underlying Android platform evolves they tend to obsolete many API's. We should be keeping on top of these so that the Android implementation stays current. However we cannot remove the old APi's completely due to the massive number of devices which Android supports. So we need to make use of Runtime checks to make sure we call the correct "supported" API's on the correct versions of Android. Previously this had to be done by checking the `SdkInt` version. With .net 6 and beyond we can make use of the `OperatingSystem.IsAndroidVersionAtLeast` utility method. This is a method which the compiler is aware of and it can hide the warnings about obsolete API's around the code it protects. Also upgraded other obsolete API's which do not need runtime checks. * fix build --- MonoGame.Framework/Media/Album.cs | 9 +- .../Platform/Android/AndroidGameWindow.cs | 8 +- .../Android/MonoGameAndroidGameView.cs | 102 +++++++++--------- .../Platform/Android/ScreenReceiver.cs | 9 +- .../Platform/Audio/OpenALSoundController.cs | 4 +- .../Platform/Graphics/OpenGL.Android.cs | 4 +- .../Platform/Graphics/Texture2D.OpenGL.cs | 4 + .../Platform/Input/GamePad.Android.cs | 20 +++- .../Platform/Media/MediaLibrary.Android.cs | 18 ++-- 9 files changed, 107 insertions(+), 71 deletions(-) diff --git a/MonoGame.Framework/Media/Album.cs b/MonoGame.Framework/Media/Album.cs index f2a7b637310..2d728761350 100644 --- a/MonoGame.Framework/Media/Album.cs +++ b/MonoGame.Framework/Media/Album.cs @@ -10,6 +10,7 @@ using MediaPlayer; using UIKit; #elif ANDROID +using Android.Content; using Android.Graphics; using Android.Provider; #endif @@ -167,7 +168,13 @@ public UIImage GetAlbumArt(int width = 0, int height = 0) #elif ANDROID public Bitmap GetAlbumArt(int width = 0, int height = 0) { - var albumArt = MediaStore.Images.Media.GetBitmap(MediaLibrary.Context.ContentResolver, this.thumbnail); + Bitmap albumArt; + if (!OperatingSystem.IsAndroidVersionAtLeast (29)) { + albumArt = MediaStore.Images.Media.GetBitmap(MediaLibrary.Context.ContentResolver, this.thumbnail); + } else { + var source = ImageDecoder.CreateSource (MediaLibrary.Context.ContentResolver, this.thumbnail); + albumArt = ImageDecoder.DecodeBitmap (source); + } if (width == 0 || height == 0) return albumArt; diff --git a/MonoGame.Framework/Platform/Android/AndroidGameWindow.cs b/MonoGame.Framework/Platform/Android/AndroidGameWindow.cs index c4865af4586..88b12475f57 100644 --- a/MonoGame.Framework/Platform/Android/AndroidGameWindow.cs +++ b/MonoGame.Framework/Platform/Android/AndroidGameWindow.cs @@ -36,11 +36,17 @@ public AndroidGameWindow(AndroidGameActivity activity, Game game) Point size; // GetRealSize() was defined in JellyBeanMr1 / API 17 / Android 4.2 - if (Build.VERSION.SdkInt < BuildVersionCodes.JellyBeanMr1) + if (!OperatingSystem.IsAndroidVersionAtLeast(17)) { size.X = activity.Resources.DisplayMetrics.WidthPixels; size.Y = activity.Resources.DisplayMetrics.HeightPixels; } + else if (OperatingSystem.IsAndroidVersionAtLeast(30)) // API 30 and Above + { + var rect = activity.WindowManager.CurrentWindowMetrics.Bounds; + size.X = rect.Width (); + size.Y = rect.Height (); + } else { Android.Graphics.Point p = new Android.Graphics.Point(); diff --git a/MonoGame.Framework/Platform/Android/MonoGameAndroidGameView.cs b/MonoGame.Framework/Platform/Android/MonoGameAndroidGameView.cs index fced5b2e901..0f3959548a2 100644 --- a/MonoGame.Framework/Platform/Android/MonoGameAndroidGameView.cs +++ b/MonoGame.Framework/Platform/Android/MonoGameAndroidGameView.cs @@ -98,7 +98,9 @@ private void Init() mHolder = Holder; // Add callback to get the SurfaceCreated etc events mHolder.AddCallback(this); +#pragma warning disable CS0618 mHolder.SetType(SurfaceType.Gpu); +#pragma warning restore CS0618 } public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Format format, int width, int height) @@ -171,8 +173,8 @@ public virtual void MakeCurrent() public virtual void ClearCurrent() { EnsureUndisposed(); - if (!egl.EglMakeCurrent(eglDisplay, EGL10.EglNoSurface, - EGL10.EglNoSurface, EGL10.EglNoContext)) + if (!egl.EglMakeCurrent(eglDisplay, IEGL10.EglNoSurface, + IEGL10.EglNoSurface, IEGL10.EglNoContext)) { System.Diagnostics.Debug.WriteLine("Error Clearing Current" + GetErrorAsString()); } @@ -770,10 +772,10 @@ protected void DestroyGLContext() protected void DestroyGLSurface() { - if (!(eglSurface == null || eglSurface == EGL10.EglNoSurface)) + if (!(eglSurface == null || eglSurface == IEGL10.EglNoSurface)) { - if (!egl.EglMakeCurrent(eglDisplay, EGL10.EglNoSurface, - EGL10.EglNoSurface, EGL10.EglNoContext)) + if (!egl.EglMakeCurrent(eglDisplay, IEGL10.EglNoSurface, + IEGL10.EglNoSurface, IEGL10.EglNoContext)) { Log.Verbose("AndroidGameView", "Could not unbind EGL surface" + GetErrorAsString()); } @@ -804,47 +806,47 @@ public int[] ToConfigAttribs() List attribs = new List(); if (Red != 0) { - attribs.Add(EGL11.EglRedSize); + attribs.Add(IEGL11.EglRedSize); attribs.Add(Red); } if (Green != 0) { - attribs.Add(EGL11.EglGreenSize); + attribs.Add(IEGL11.EglGreenSize); attribs.Add(Green); } if (Blue != 0) { - attribs.Add(EGL11.EglBlueSize); + attribs.Add(IEGL11.EglBlueSize); attribs.Add(Blue); } if (Alpha != 0) { - attribs.Add(EGL11.EglAlphaSize); + attribs.Add(IEGL11.EglAlphaSize); attribs.Add(Alpha); } if (Depth != 0) { - attribs.Add(EGL11.EglDepthSize); + attribs.Add(IEGL11.EglDepthSize); attribs.Add(Depth); } if (Stencil != 0) { - attribs.Add(EGL11.EglStencilSize); + attribs.Add(IEGL11.EglStencilSize); attribs.Add(Stencil); } if (SampleBuffers != 0) { - attribs.Add(EGL11.EglSampleBuffers); + attribs.Add(IEGL11.EglSampleBuffers); attribs.Add(SampleBuffers); } if (Samples != 0) { - attribs.Add(EGL11.EglSamples); + attribs.Add(IEGL11.EglSamples); attribs.Add(Samples); } - attribs.Add(EGL11.EglRenderableType); + attribs.Add(IEGL11.EglRenderableType); attribs.Add(4); - attribs.Add(EGL11.EglNone); + attribs.Add(IEGL11.EglNone); return attribs.ToArray(); } @@ -860,14 +862,14 @@ public static SurfaceConfig FromEGLConfig (EGLConfig config, IEGL10 egl, EGLDisp { return new SurfaceConfig() { - Red = GetAttribute(config, egl, eglDisplay, EGL11.EglRedSize), - Green = GetAttribute(config, egl, eglDisplay, EGL11.EglGreenSize), - Blue = GetAttribute(config, egl, eglDisplay, EGL11.EglBlueSize), - Alpha = GetAttribute(config, egl, eglDisplay, EGL11.EglAlphaSize), - Depth = GetAttribute(config, egl, eglDisplay, EGL11.EglDepthSize), - Stencil = GetAttribute(config, egl, eglDisplay, EGL11.EglStencilSize), - SampleBuffers = GetAttribute(config, egl, eglDisplay, EGL11.EglSampleBuffers), - Samples = GetAttribute(config, egl, eglDisplay, EGL11.EglSamples) + Red = GetAttribute(config, egl, eglDisplay, IEGL11.EglRedSize), + Green = GetAttribute(config, egl, eglDisplay, IEGL11.EglGreenSize), + Blue = GetAttribute(config, egl, eglDisplay, IEGL11.EglBlueSize), + Alpha = GetAttribute(config, egl, eglDisplay, IEGL11.EglAlphaSize), + Depth = GetAttribute(config, egl, eglDisplay, IEGL11.EglDepthSize), + Stencil = GetAttribute(config, egl, eglDisplay, IEGL11.EglStencilSize), + SampleBuffers = GetAttribute(config, egl, eglDisplay, IEGL11.EglSampleBuffers), + Samples = GetAttribute(config, egl, eglDisplay, IEGL11.EglSamples) }; } @@ -883,8 +885,8 @@ protected void CreateGLContext() egl = EGLContext.EGL.JavaCast(); - eglDisplay = egl.EglGetDisplay(EGL10.EglDefaultDisplay); - if (eglDisplay == EGL10.EglNoDisplay) + eglDisplay = egl.EglGetDisplay(IEGL10.EglDefaultDisplay); + if (eglDisplay == IEGL10.EglNoDisplay) throw new Exception("Could not get EGL display" + GetErrorAsString()); int[] version = new int[2]; @@ -975,17 +977,17 @@ protected void CreateGLContext() var createdVersion = new MonoGame.OpenGL.GLESVersion(); foreach (var v in MonoGame.OpenGL.GLESVersion.GetSupportedGLESVersions ()) { Log.Verbose("AndroidGameView", "Creating GLES {0} Context", v); - eglContext = egl.EglCreateContext(eglDisplay, results[0], EGL10.EglNoContext, v.GetAttributes()); - if (eglContext == null || eglContext == EGL10.EglNoContext) + eglContext = egl.EglCreateContext(eglDisplay, results[0], IEGL10.EglNoContext, v.GetAttributes()); + if (eglContext == null || eglContext == IEGL10.EglNoContext) { Log.Verbose("AndroidGameView", string.Format("GLES {0} Not Supported. {1}", v, GetErrorAsString())); - eglContext = EGL10.EglNoContext; + eglContext = IEGL10.EglNoContext; continue; } createdVersion = v; break; } - if (eglContext == null || eglContext == EGL10.EglNoContext) + if (eglContext == null || eglContext == IEGL10.EglNoContext) { eglContext = null; throw new Exception("Could not create EGL context" + GetErrorAsString()); @@ -999,35 +1001,35 @@ private string GetErrorAsString() { switch (egl.EglGetError()) { - case EGL10.EglSuccess: + case IEGL10.EglSuccess: return "Success"; - case EGL10.EglNotInitialized: + case IEGL10.EglNotInitialized: return "Not Initialized"; - case EGL10.EglBadAccess: + case IEGL10.EglBadAccess: return "Bad Access"; - case EGL10.EglBadAlloc: + case IEGL10.EglBadAlloc: return "Bad Allocation"; - case EGL10.EglBadAttribute: + case IEGL10.EglBadAttribute: return "Bad Attribute"; - case EGL10.EglBadConfig: + case IEGL10.EglBadConfig: return "Bad Config"; - case EGL10.EglBadContext: + case IEGL10.EglBadContext: return "Bad Context"; - case EGL10.EglBadCurrentSurface: + case IEGL10.EglBadCurrentSurface: return "Bad Current Surface"; - case EGL10.EglBadDisplay: + case IEGL10.EglBadDisplay: return "Bad Display"; - case EGL10.EglBadMatch: + case IEGL10.EglBadMatch: return "Bad Match"; - case EGL10.EglBadNativePixmap: + case IEGL10.EglBadNativePixmap: return "Bad Native Pixmap"; - case EGL10.EglBadNativeWindow: + case IEGL10.EglBadNativeWindow: return "Bad Native Window"; - case EGL10.EglBadParameter: + case IEGL10.EglBadParameter: return "Bad Parameter"; - case EGL10.EglBadSurface: + case IEGL10.EglBadSurface: return "Bad Surface"; default: @@ -1045,7 +1047,7 @@ protected void CreateGLSurface() DestroyGLSurface(); eglSurface = egl.EglCreateWindowSurface(eglDisplay, eglConfig, (Java.Lang.Object)this.Holder, null); - if (eglSurface == null || eglSurface == EGL10.EglNoSurface) + if (eglSurface == null || eglSurface == IEGL10.EglNoSurface) throw new Exception("Could not create EGL window surface" + GetErrorAsString()); if (!egl.EglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) @@ -1073,7 +1075,7 @@ protected EGLSurface CreatePBufferSurface(EGLConfig config, int[] attribList) { IEGL10 egl = EGLContext.EGL.JavaCast(); EGLSurface result = egl.EglCreatePbufferSurface(eglDisplay, config, attribList); - if (result == null || result == EGL10.EglNoSurface) + if (result == null || result == IEGL10.EglNoSurface) throw new Exception("EglCreatePBufferSurface"); return result; } @@ -1323,21 +1325,21 @@ public BackgroundContext(MonoGameAndroidGameView view) this.view = view; foreach (var v in MonoGame.OpenGL.GLESVersion.GetSupportedGLESVersions()) { - eglContext = view.egl.EglCreateContext(view.eglDisplay, view.eglConfig, EGL10.EglNoContext, v.GetAttributes()); - if (eglContext == null || eglContext == EGL10.EglNoContext) + eglContext = view.egl.EglCreateContext(view.eglDisplay, view.eglConfig, IEGL10.EglNoContext, v.GetAttributes()); + if (eglContext == null || eglContext == IEGL10.EglNoContext) { continue; } break; } - if (eglContext == null || eglContext == EGL10.EglNoContext) + if (eglContext == null || eglContext == IEGL10.EglNoContext) { eglContext = null; throw new Exception("Could not create EGL context" + view.GetErrorAsString()); } - int[] pbufferAttribList = new int[] { EGL10.EglWidth, 64, EGL10.EglHeight, 64, EGL10.EglNone }; + int[] pbufferAttribList = new int[] { IEGL10.EglWidth, 64, IEGL10.EglHeight, 64, IEGL10.EglNone }; surface = view.CreatePBufferSurface(view.eglConfig, pbufferAttribList); - if (surface == EGL10.EglNoSurface) + if (surface == IEGL10.EglNoSurface) throw new Exception("Could not create Pbuffer Surface" + view.GetErrorAsString()); } diff --git a/MonoGame.Framework/Platform/Android/ScreenReceiver.cs b/MonoGame.Framework/Platform/Android/ScreenReceiver.cs index 24832b8742b..4eb357cfaa9 100644 --- a/MonoGame.Framework/Platform/Android/ScreenReceiver.cs +++ b/MonoGame.Framework/Platform/Android/ScreenReceiver.cs @@ -24,8 +24,13 @@ public override void OnReceive(Context context, Intent intent) // and if not re-enable the game related functions. // http://stackoverflow.com/questions/4260794/how-to-tell-if-device-is-sleeping KeyguardManager keyguard = (KeyguardManager)context.GetSystemService(Context.KeyguardService); - if (!keyguard.InKeyguardRestrictedInputMode()) - OnUnlocked(); + if (!OperatingSystem.IsAndroidVersionAtLeast (28)) { + if (!keyguard.InKeyguardRestrictedInputMode()) + OnUnlocked(); + } else { + if (!keyguard.IsDeviceLocked) + OnUnlocked(); + } } else if(intent.Action == Intent.ActionUserPresent) { diff --git a/MonoGame.Framework/Platform/Audio/OpenALSoundController.cs b/MonoGame.Framework/Platform/Audio/OpenALSoundController.cs index 844e6320abc..9b18c30836e 100644 --- a/MonoGame.Framework/Platform/Audio/OpenALSoundController.cs +++ b/MonoGame.Framework/Platform/Audio/OpenALSoundController.cs @@ -197,7 +197,7 @@ Now use OpenSL ES to create an AudioPlayer with PCM buffer queue data locator. int frequency = DEFAULT_FREQUENCY; int updateSize = DEFAULT_UPDATE_SIZE; int updateBuffers = DEFAULT_UPDATE_BUFFER_COUNT; - if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.JellyBeanMr1) + if (OperatingSystem.IsAndroidVersionAtLeast(17)) { Android.Util.Log.Debug("OAL", Game.Activity.PackageManager.HasSystemFeature(PackageManager.FeatureAudioLowLatency) ? "Supports low latency audio playback." : "Does not support low latency audio playback."); @@ -214,7 +214,7 @@ Now use OpenSL ES to create an AudioPlayer with PCM buffer queue data locator. // If 4.4 or higher, then we don't need to double buffer on the application side. // See http://stackoverflow.com/a/15006327 - if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat) + if (OperatingSystem.IsAndroidVersionAtLeast (19)) { updateBuffers = 1; } diff --git a/MonoGame.Framework/Platform/Graphics/OpenGL.Android.cs b/MonoGame.Framework/Platform/Graphics/OpenGL.Android.cs index f3e7e6734ec..bc5be2b28a9 100644 --- a/MonoGame.Framework/Platform/Graphics/OpenGL.Android.cs +++ b/MonoGame.Framework/Platform/Graphics/OpenGL.Android.cs @@ -76,8 +76,8 @@ struct GLESVersion internal int[] GetAttributes() { - int minor = Minor > -1 ? EglContextMinorVersion : EGL10.EglNone; - return new int[] { EglContextClientVersion, Major, minor, Minor, EGL10.EglNone }; + int minor = Minor > -1 ? EglContextMinorVersion : IEGL10.EglNone; + return new int[] { EglContextClientVersion, Major, minor, Minor, IEGL10.EglNone }; } public override string ToString() diff --git a/MonoGame.Framework/Platform/Graphics/Texture2D.OpenGL.cs b/MonoGame.Framework/Platform/Graphics/Texture2D.OpenGL.cs index 165b08716a8..5f545b71d43 100644 --- a/MonoGame.Framework/Platform/Graphics/Texture2D.OpenGL.cs +++ b/MonoGame.Framework/Platform/Graphics/Texture2D.OpenGL.cs @@ -392,10 +392,14 @@ private void FillTextureFromStream(Stream stream) using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options { InScaled = false, +#pragma warning disable CA1422 InDither = false, +#pragma warning restore CA1422 InJustDecodeBounds = false, +#pragma warning disable CS0618 InPurgeable = true, InInputShareable = true, +#pragma warning restore CS0618 })) { var width = image.Width; diff --git a/MonoGame.Framework/Platform/Input/GamePad.Android.cs b/MonoGame.Framework/Platform/Input/GamePad.Android.cs index 66d2328458d..aebd6e65ffc 100644 --- a/MonoGame.Framework/Platform/Input/GamePad.Android.cs +++ b/MonoGame.Framework/Platform/Input/GamePad.Android.cs @@ -2,6 +2,8 @@ // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. +using System; +using Android.OS; using Android.Views; namespace Microsoft.Xna.Framework.Input @@ -35,7 +37,10 @@ private static GamePadCapabilities CapabilitiesOfDevice(InputDevice device) var capabilities = new GamePadCapabilities(); capabilities.IsConnected = true; capabilities.GamePadType = GamePadType.GamePad; - capabilities.HasLeftVibrationMotor = capabilities.HasRightVibrationMotor = device.Vibrator.HasVibrator; + capabilities.HasLeftVibrationMotor = capabilities.HasRightVibrationMotor = + !OperatingSystem.IsAndroidVersionAtLeast (31) ? + device.Vibrator.HasVibrator : + device.VibratorManager.DefaultVibrator.HasVibrator; // build out supported inputs from what the gamepad exposes int[] keyMap = new int[16]; @@ -63,7 +68,7 @@ private static GamePadCapabilities CapabilitiesOfDevice(InputDevice device) // get a bool[] with indices matching the keyMap bool[] hasMap = new bool[16]; // HasKeys() was defined in Kitkat / API19 / Android 4.4 - if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Kitkat) + if (!OperatingSystem.IsAndroidVersionAtLeast(19)) { var keyMap2 = new Keycode[keyMap.Length]; for(int i=0; i progressCallback) // See: https://code.google.com/p/android/issues/detail?id=1630 // Workaround: http://stackoverflow.com/questions/1954434/cover-art-on-android - int albumNameColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AlbumColumns.Album); - int albumArtistColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AlbumColumns.Artist); - int albumIdColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AlbumColumns.AlbumId); - int genreColumn = musicCursor.GetColumnIndex(MediaStore.Audio.GenresColumns.Name); // Also broken :( - - int artistColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AudioColumns.Artist); - int titleColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AudioColumns.Title); - int durationColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AudioColumns.Duration); - int assetIdColumn = musicCursor.GetColumnIndex(MediaStore.Audio.AudioColumns.Id); + int albumNameColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IAlbumColumns.Album); + int albumArtistColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IAlbumColumns.Artist); + int albumIdColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IAlbumColumns.AlbumId); + int genreColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IGenresColumns.Name); // Also broken :( + + int artistColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IAudioColumns.Artist); + int titleColumn = musicCursor.GetColumnIndex(MediaStore.IMediaColumns.Title); + int durationColumn = musicCursor.GetColumnIndex(MediaStore.Audio.IAudioColumns.Duration); + int assetIdColumn = musicCursor.GetColumnIndex(IBaseColumns.Id); if (titleColumn == -1 || durationColumn == -1 || assetIdColumn == -1) { From f9d495127abf9e9bf2cbe8ff35d10aae04447f50 Mon Sep 17 00:00:00 2001 From: Roman Shapiro Date: Fri, 20 Sep 2024 22:32:45 +0700 Subject: [PATCH 4/6] Updated to the latest StbImageSharp (#8494) * Updated to the latest StbImageSharp * StbImageSharp: Removed stackalloc initializers --- ThirdParty/StbImageSharp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThirdParty/StbImageSharp b/ThirdParty/StbImageSharp index 55543eb8f06..0ec6394bb71 160000 --- a/ThirdParty/StbImageSharp +++ b/ThirdParty/StbImageSharp @@ -1 +1 @@ -Subproject commit 55543eb8f061fe11f148c90bc681cf748d372806 +Subproject commit 0ec6394bb7184e0576a3fa2e382a487c7ee82e9b From 2dd7b76bec5c02e9d30a900fb33f8914e4e3e9f8 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Mon, 23 Sep 2024 23:08:16 +0100 Subject: [PATCH 5/6] Add Self Hosted Runner for Tests (#8493) This enables the UI unit tests on some self hosted machines we have available. There were some issues regarding running UI based tests in NUnitLite via dotnet test on MacOS. This is because you MUST create NSWindow instances on the Main Thread. So we had to modify the Test runner to marshal the UI tests over to the main thread. This added a new [RunOnUI] attribute, which can be used to flag a test which MUST run on the UI thread. This works for all platforms. There were still some slight issues with the test on MacOS if running ALL the UI tests in on go they would fail. But running them in smaller batches works. I suspect that there is a bug in one of the tests which is causing this we need to track it down. A few tests have been disable, issues need to be opened for these so that they can be fixed. Also fixed Short2 and NormalizedByte4 types so they actually pass the tests. Fixed the casing on the Artifacts folder so it is consistent across all platforms (Linux and Mac were using lower case in some areas). Fixed the Adpcm audio support so it unpacks the data correctly. --- .github/workflows/main.yml | 294 +++++++++++++++++- .gitignore | 1 + .vscode/launch.json | 15 +- .vscode/settings.json | 6 + .vscode/tasks.json | 12 + .../Graphics/PackedVector/NormalizedByte4.cs | 8 +- .../Graphics/PackedVector/Short2.cs | 4 +- .../Platform/Audio/OALSoundBuffer.cs | 6 +- .../Assets/Projects/BuildSimpleProject.csproj | 4 +- .../Audio/DynamicSoundEffectInstanceTest.cs | 1 + .../Audio/SoundEffectInstanceTest.cs | 1 + Tests/Framework/Audio/SoundEffectTest.cs | 1 + Tests/Framework/Audio/XactTest.cs | 26 ++ Tests/Framework/FrameworkDispatcherTest.cs | 1 + Tests/Framework/GameTest+Methods.cs | 1 + Tests/Framework/GameTest+Properties.cs | 11 + Tests/Framework/GameTest.cs | 3 + Tests/Framework/Graphics/BlendStateTest.cs | 5 + .../Graphics/DepthStencilStateTest.cs | 6 + Tests/Framework/Graphics/EffectTest.cs | 7 + .../Framework/Graphics/GraphicsAdapterTest.cs | 13 +- .../Graphics/GraphicsDeviceManagerTest.cs | 20 ++ .../Framework/Graphics/GraphicsDeviceTest.cs | 24 ++ .../Graphics/GraphicsDeviceTestFixtureBase.cs | 4 +- Tests/Framework/Graphics/IndexBufferTest.cs | 6 + .../Framework/Graphics/MiscellaneousTests.cs | 3 + Tests/Framework/Graphics/ModelTest.cs | 8 + .../Framework/Graphics/OcclusionQueryTest.cs | 4 + .../Framework/Graphics/RasterizerStateTest.cs | 13 + .../Framework/Graphics/RenderTarget2DTest.cs | 12 + .../Graphics/RenderTargetCubeTest.cs | 9 +- Tests/Framework/Graphics/SamplerStateTest.cs | 6 + .../Graphics/ScissorRectangleTest.cs | 8 + Tests/Framework/Graphics/ShaderTest.cs | 3 + Tests/Framework/Graphics/SpriteBatchTest.cs | 25 +- Tests/Framework/Graphics/SpriteFontTest.cs | 23 +- .../Graphics/Texture2DNonVisualTest.cs | 50 ++- Tests/Framework/Graphics/Texture2DTest.cs | 12 + .../Graphics/Texture3DNonVisualTest.cs | 14 +- Tests/Framework/Graphics/Texture3DTest.cs | 5 +- Tests/Framework/Graphics/TextureCubeTest.cs | 12 + Tests/Framework/Graphics/VertexBufferTest.cs | 29 ++ Tests/Framework/Graphics/ViewportTest.cs | 5 + Tests/Framework/Visual/MiscellaneousTests.cs | 4 + Tests/MonoGame.Tests.DesktopGL.csproj | 3 + .../MainThreadSynchronizationContext.cs | 60 ++++ Tests/Runner/Desktop/RunOnUIAttribute.cs | 33 ++ Tests/Runner/Extensions.cs | 30 +- Tests/Runner/Program.cs | 47 ++- .../MonoGame.Tools.Tests/AudioContentTests.cs | 4 +- .../EffectProcessorTests.cs | 4 +- .../MonoGame.Tools.Tests.csproj | 10 + .../MonoGame.Tools.Tests/Mp3ImporterTests.cs | 4 +- .../MonoGame.Tools.Tests/OggImporterTests.cs | 4 +- .../TextureImporterTests.cs | 2 +- .../TextureProcessorTests.cs | 1 + .../MonoGame.Tools.Tests/WavImporterTests.cs | 4 +- .../MonoGame.Tools.Tests/WmaImporterTests.cs | 4 +- build/BuildContext.cs | 4 +- build/BuildTestsTasks/BuildTestsTask.cs | 15 + build/BuildToolsTasks/BuildToolTestsTask.cs | 2 +- build/DeployTasks/UploadArtifactsTask.cs | 6 +- build/Tasks.cs | 11 +- build/TestTasks/DownloadTestArtifactsTask.cs | 23 ++ 64 files changed, 936 insertions(+), 60 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Tests/Runner/Desktop/MainThreadSynchronizationContext.cs create mode 100644 Tests/Runner/Desktop/RunOnUIAttribute.cs create mode 100644 build/BuildTestsTasks/BuildTestsTask.cs create mode 100644 build/TestTasks/DownloadTestArtifactsTask.cs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 62daee63386..79ccd22853b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,7 +57,7 @@ jobs: if: runner.os == 'macOS' - name: Setup Wine - run: wget -qO- https://monogame.net/downloads/net8_mgfxc_wine_setup.sh | bash + run: wget -qO- https://monogame.net/downloads/net9_mgfxc_wine_setup.sh | bash if: runner.os != 'Windows' - name: Install required workloads @@ -75,7 +75,7 @@ jobs: run: dotnet run --project build/Build.csproj -- --target=Default - name: Test - run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release + run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release --filter="TestCategory!=Audio" env: DOTNET_ROOT: ${{github.workspace}}/dotnet64 MGFXC_WINE_PATH: /home/runner/.winemonogame @@ -83,7 +83,7 @@ jobs: if: runner.os == 'Linux' - name: Test - run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release + run: dotnet test Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj --blame-hang-timeout 1m -c Release --filter="TestCategory!=Audio" env: DOTNET_ROOT: ${{github.workspace}}/dotnet64 MGFXC_WINE_PATH: /Users/runner/.winemonogame @@ -141,3 +141,291 @@ jobs: artifacts: "nugets/*.nupkg" token: ${{ secrets.GITHUB_TOKEN }} + tests: + name: tests-${{ matrix.os }} + needs: [ build ] + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: windows + platform: windows + - os: macos + platform: macos + - os: ubuntu-latest + platform: linux + filter: --where="Category != Audio" + # - os: linux + # platform: linux + fail-fast: false + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: install wine64 on linux + run: | + sudo apt install p7zip-full curl + sudo dpkg --add-architecture i386 + sudo mkdir -pm755 /etc/apt/keyrings + sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key + sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources + sudo apt update && sudo apt install --install-recommends winehq-stable + if: runner.os == 'Linux' && runner.environment == 'github-hosted' + + - name: Install Arial Font + run: | + echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | sudo debconf-set-selections + sudo apt install -y ttf-mscorefonts-installer + sudo fc-cache + fc-match Arial + if: runner.os == 'Linux' && runner.environment == 'github-hosted' + + - name: Setup Wine + run: wget -qO- https://monogame.net/downloads/net9_mgfxc_wine_setup.sh | bash + if: runner.os != 'Windows' && runner.environment == 'github-hosted' + + - name: Download tests-tools-${{ matrix.platform }} + uses: actions/download-artifact@v3 + with: + name: tests-tools-${{ matrix.platform }} + path: tests-tools + + - name: Download tests-desktopgl-${{ matrix.platform }} + uses: actions/download-artifact@v3 + with: + name: tests-desktopgl-${{ matrix.platform }} + path: tests-desktopgl + + - name: Download tests-windowsdx-${{ matrix.platform }} + uses: actions/download-artifact@v3 + with: + name: tests-windowsdx-${{ matrix.platform }} + path: tests-windowsdx + if: runner.os == 'Windows' + + - name: Install Tools + run: | + dotnet tool install --create-manifest-if-needed mgcb-basisu + dotnet tool install --create-manifest-if-needed mgcb-crunch + + - name: Run Tools Tests + run: dotnet test tests-tools/MonoGame.Tools.Tests.dll --blame-hang-timeout 1m --filter="TestCategory!=Effects" + env: + CI: true + + - name: Run DirectX Tests + shell: cmd + run: dotnet MonoGame.Tests.dll + env: + CI: true + working-directory: tests-windowsdx + if: runner.os == 'Windows' + + # Run the DesktopGL tests on all platforms using NUnitLite runner not dotnet test + # We have to run this is bits because the tests crash if too many are run in one go? + - name: Run Framework Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Framework ${{matrix.filter}} + env: + CI: true + working-directory: tests-desktopgl + + - name: Run Audio Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Audio + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Input Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Input + env: + CI: true + working-directory: tests-desktopgl + + - name: Run Visual Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Visual + env: + CI: true + working-directory: tests-desktopgl + + - name: Run Game Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --where="Category = GameTest" + env: + CI: true + working-directory: tests-desktopgl + + - name: Run Graphics.BlendStateTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.BlendStateTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.DepthStencilStateTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.DepthStencilStateTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.EffectTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.EffectTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.GraphicsAdapterTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.GraphicsAdapterTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + # This test hangs on MacOS? + # - name: Run Graphics.GraphicsDeviceTest Tests + # run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.GraphicsDeviceTest + # env: + # CI: true + # working-directory: tests-desktopgl + # if: runner.environment != 'github-hosted' + + - name: Run Graphics.IndexBufferTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.IndexBufferTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.MiscellaneousTests Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.MiscellaneousTests + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.ModelTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.ModelTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.OcclusionQueryTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.OcclusionQueryTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.RasterizerStateTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.RasterizerStateTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.RenderTarget2DTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.RenderTarget2DTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.RenderTargetCubeTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.RenderTargetCubeTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.SamplerStateTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.SamplerStateTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.ScissorRectangleTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.ScissorRectangleTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.ShaderTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.ShaderTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.SpriteBatchTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.SpriteBatchTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.SpriteFontTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.SpriteFontTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.Texture2DNonVisualTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.Texture2DNonVisualTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.Texture2DTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.Texture2DTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.Texture3DNonVisualTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.Texture3DNonVisualTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.Texture3DTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.Texture3DTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.TextureCubeTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.TextureCubeTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.VertexBufferTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.VertexBufferTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' + + - name: Run Graphics.ViewportTest Tests + run: dotnet MonoGame.Tests.dll --timeout=300000 --test MonoGame.Tests.Graphics.ViewportTest + env: + CI: true + working-directory: tests-desktopgl + if: runner.environment != 'github-hosted' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8f0a0f8f04c..7594fe9ed3a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ project.lock.json /MonoGame.Framework/MonoGame.Framework.Net.WindowsUniversal.project.lock.json /MonoGame.Framework/MonoGame.Framework.WindowsUniversal.project.lock.json artifacts/ +Artifacts/ # JetBrains Rider .idea/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 73fe90c937a..e0521e1c38e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,7 +20,20 @@ "type": "coreclr", "request": "attach", "processId": "${input.processid}", - } + }, + { + "name": "MonoGame.Tests", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build-tests", + "program": "${workspaceFolder}/Artifacts/Tests/DesktopGL/Debug/MonoGame.Tests", + "args": [ + "--test=MonoGame.Tests.Graphics.SpriteBatchTest.Draw_normal" + ], + "cwd": "${workspaceFolder}/Artifacts/Tests/DesktopGL/Debug/", + "console": "internalConsole", + "stopAtEntry": false + }, ], "inputs": [ { diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..b405c27db5a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "dotnetCoreExplorer.searchpatterns": [ + "Artifacts/Tests/**/MonoGame.Tests.dll", + "Artifacts/Tests/**/MonoGame.Tools.Tests.dll" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff4ce21d72a..ee1b2400981 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,6 +12,18 @@ "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" + }, + { + "label": "build-tests", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Tests/MonoGame.Tests.DesktopGL.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" } ] } \ No newline at end of file diff --git a/MonoGame.Framework/Graphics/PackedVector/NormalizedByte4.cs b/MonoGame.Framework/Graphics/PackedVector/NormalizedByte4.cs index 772cc0616c2..b8ea9d3eaa4 100644 --- a/MonoGame.Framework/Graphics/PackedVector/NormalizedByte4.cs +++ b/MonoGame.Framework/Graphics/PackedVector/NormalizedByte4.cs @@ -99,10 +99,10 @@ public override string ToString() private static uint Pack(float x, float y, float z, float w) { - var byte4 = (((uint) MathF.Round(MathHelper.Clamp(x, -1.0f, 1.0f) * 127.0f)) & 0xff) << 0; - var byte3 = (((uint) MathF.Round(MathHelper.Clamp(y, -1.0f, 1.0f) * 127.0f)) & 0xff) << 8; - var byte2 = (((uint) MathF.Round(MathHelper.Clamp(z, -1.0f, 1.0f) * 127.0f)) & 0xff) << 16; - var byte1 = (((uint) MathF.Round(MathHelper.Clamp(w, -1.0f, 1.0f) * 127.0f)) & 0xff) << 24; + var byte4 = (uint)(((int) MathF.Round(MathHelper.Clamp(x, -1.0f, 1.0f) * 127.0f)) & 0xff) << 0; + var byte3 = (uint)(((int) MathF.Round(MathHelper.Clamp(y, -1.0f, 1.0f) * 127.0f)) & 0xff) << 8; + var byte2 = (uint)(((int) MathF.Round(MathHelper.Clamp(z, -1.0f, 1.0f) * 127.0f)) & 0xff) << 16; + var byte1 = (uint)(((int) MathF.Round(MathHelper.Clamp(w, -1.0f, 1.0f) * 127.0f)) & 0xff) << 24; return byte4 | byte3 | byte2 | byte1; } diff --git a/MonoGame.Framework/Graphics/PackedVector/Short2.cs b/MonoGame.Framework/Graphics/PackedVector/Short2.cs index 5d03aa16279..31c47b60fc1 100644 --- a/MonoGame.Framework/Graphics/PackedVector/Short2.cs +++ b/MonoGame.Framework/Graphics/PackedVector/Short2.cs @@ -115,8 +115,8 @@ private static uint PackInTwo (float vectorX, float vectorY) const float minNeg = ~(int)maxPos; // two's complement // clamp the value between min and max values - var word2 = ((uint) MathF.Round(MathHelper.Clamp(vectorX, minNeg, maxPos)) & 0xFFFF); - var word1 = (((uint) MathF.Round(MathHelper.Clamp(vectorY, minNeg, maxPos)) & 0xFFFF) << 0x10); + var word2 = (uint)((int) MathF.Round(MathHelper.Clamp(vectorX, minNeg, maxPos)) & 0xFFFF); + var word1 = (uint)(((int) MathF.Round(MathHelper.Clamp(vectorY, minNeg, maxPos)) & 0xFFFF) << 0x10); return (word2 | word1); } diff --git a/MonoGame.Framework/Platform/Audio/OALSoundBuffer.cs b/MonoGame.Framework/Platform/Audio/OALSoundBuffer.cs index b0e8025bcbb..2a6f4c86fd8 100644 --- a/MonoGame.Framework/Platform/Audio/OALSoundBuffer.cs +++ b/MonoGame.Framework/Platform/Audio/OALSoundBuffer.cs @@ -67,7 +67,11 @@ public void BindDataBuffer(byte[] dataBuffer, ALFormat format, int size, int sam ALHelper.CheckError("Failed to get buffer channels"); AL.GetBuffer(openALDataBuffer, ALGetBufferi.Size, out unpackedSize); ALHelper.CheckError("Failed to get buffer size"); - Duration = (float)(unpackedSize / ((bits / 8) * channels)) / (float)sampleRate; + if (format == ALFormat.MonoMSAdpcm || format == ALFormat.StereoMSAdpcm) { + Duration = (float)(unpackedSize * 2) / (channels * sampleRate);; + } else { + Duration = (float)(unpackedSize * 8) / (channels * bits * sampleRate); + } } public void Dispose() diff --git a/Tests/Assets/Projects/BuildSimpleProject.csproj b/Tests/Assets/Projects/BuildSimpleProject.csproj index ead23a2b9a1..6504e3099b7 100644 --- a/Tests/Assets/Projects/BuildSimpleProject.csproj +++ b/Tests/Assets/Projects/BuildSimpleProject.csproj @@ -1,6 +1,6 @@  - + Exe net8.0 @@ -12,5 +12,5 @@ - + diff --git a/Tests/Framework/Audio/DynamicSoundEffectInstanceTest.cs b/Tests/Framework/Audio/DynamicSoundEffectInstanceTest.cs index d065142a862..1f2f73f77d1 100644 --- a/Tests/Framework/Audio/DynamicSoundEffectInstanceTest.cs +++ b/Tests/Framework/Audio/DynamicSoundEffectInstanceTest.cs @@ -11,6 +11,7 @@ namespace MonoGame.Tests.Audio { + [Category("Audio")] class DynamicSoundEffectInstanceTest { [SetUp] diff --git a/Tests/Framework/Audio/SoundEffectInstanceTest.cs b/Tests/Framework/Audio/SoundEffectInstanceTest.cs index e8187200be6..fec843b523a 100644 --- a/Tests/Framework/Audio/SoundEffectInstanceTest.cs +++ b/Tests/Framework/Audio/SoundEffectInstanceTest.cs @@ -14,6 +14,7 @@ namespace MonoGame.Tests.Audio { + [Category("Audio")] class SoundEffectInstanceTest { [SetUp] diff --git a/Tests/Framework/Audio/SoundEffectTest.cs b/Tests/Framework/Audio/SoundEffectTest.cs index c2764110905..34535581bfb 100644 --- a/Tests/Framework/Audio/SoundEffectTest.cs +++ b/Tests/Framework/Audio/SoundEffectTest.cs @@ -12,6 +12,7 @@ namespace MonoGame.Tests.Audio { + [Category("Audio")] public class SoundEffectTests { [SetUp] diff --git a/Tests/Framework/Audio/XactTest.cs b/Tests/Framework/Audio/XactTest.cs index c46163e89ed..8bf748fb890 100644 --- a/Tests/Framework/Audio/XactTest.cs +++ b/Tests/Framework/Audio/XactTest.cs @@ -12,7 +12,9 @@ namespace MonoGame.Tests.Audio { + [TestFixture] + [Category("Audio")] public class XactTests { private AudioEngine _audioEngine; @@ -355,6 +357,30 @@ public void CueSetVariable() cue.Dispose(); } + [Test] + public void WaveBankPlays() + { + var waveBank = new WaveBank(_audioEngine, @"Assets\Audio\Win\Tests.xwb"); + Assert.False(waveBank.IsInUse); + Assert.False(waveBank.IsDisposed); + Assert.True(waveBank.IsPrepared); + + var sei = _soundBank.GetSoundEffectInstance (0, 0, out bool streaming); + sei.Play (); + Assert.True(sei.State == SoundState.Playing); + sei = _soundBank.GetSoundEffectInstance (0, 1, out streaming); + sei.Play (); + Assert.True(sei.State == SoundState.Playing); + sei = _soundBank.GetSoundEffectInstance (0, 2, out streaming); + sei.Play (); + Assert.True(sei.State == SoundState.Playing); + + waveBank.Dispose(); + Assert.True(waveBank.IsDisposed); + Assert.False(waveBank.IsInUse); + Assert.False(waveBank.IsPrepared); + } + private void SleepWhileAudioEngineUpdates(int ms) { Stopwatch stopwatch = new Stopwatch(); diff --git a/Tests/Framework/FrameworkDispatcherTest.cs b/Tests/Framework/FrameworkDispatcherTest.cs index 95e7cc03058..b27461df156 100644 --- a/Tests/Framework/FrameworkDispatcherTest.cs +++ b/Tests/Framework/FrameworkDispatcherTest.cs @@ -54,6 +54,7 @@ enum CallOnAnotherThreadTestResult #if !XNA [Test] + [Category ("Audio")] public void UpdatesSoundEffectInstancePool() { FrameworkDispatcher.Update(); diff --git a/Tests/Framework/GameTest+Methods.cs b/Tests/Framework/GameTest+Methods.cs index e5ec1a586d2..f694d90308b 100644 --- a/Tests/Framework/GameTest+Methods.cs +++ b/Tests/Framework/GameTest+Methods.cs @@ -13,6 +13,7 @@ namespace MonoGame.Tests { partial class GameTest { public static class Methods { [TestFixture] + [Category("GameTest")] public class Run : FixtureBase { [Test, Ignore("Fix me!")] public void Can_only_be_called_once () diff --git a/Tests/Framework/GameTest+Properties.cs b/Tests/Framework/GameTest+Properties.cs index 2fcc4e8f1c9..c52c11434ed 100644 --- a/Tests/Framework/GameTest+Properties.cs +++ b/Tests/Framework/GameTest+Properties.cs @@ -23,6 +23,7 @@ partial class GameTest public static class Properties { [TestFixture] + [Category("GameTest")] public class Components : ReadOnlyPropertyFixtureBase { public Components () @@ -39,6 +40,7 @@ public void Is_available_before_Run () } [TestFixture] + [Category("GameTest")] public class Content : ReadWritePropertyFixtureBase { public Content () : base (g => g.Content) @@ -70,6 +72,7 @@ public void Is_not_provided_as_a_service () } [TestFixture] + [Category("GameTest")] public class GraphicsDevice_ : ReadOnlyPropertyFixtureBase { public GraphicsDevice_ () : base (g => g.GraphicsDevice) @@ -118,6 +121,7 @@ private class MockGraphicsDeviceService : IGraphicsDeviceService } [TestFixture] + [Category("GameTest")] public class InactiveSleepTime : ReadWritePropertyFixtureBase { public InactiveSleepTime () : base (g => g.InactiveSleepTime) @@ -135,6 +139,7 @@ public InactiveSleepTime () } [TestFixture] + [Category("GameTest")] public class IsActive : ReadOnlyPropertyFixtureBase { public IsActive () : base (g => g.IsActive) @@ -144,6 +149,7 @@ public IsActive () } [TestFixture] + [Category("GameTest")] public class IsFixedTimeStep : ReadWritePropertyFixtureBase { public IsFixedTimeStep () : base (g => g.IsFixedTimeStep) @@ -158,6 +164,7 @@ public override void Cannot_set_illegal_value (Tuple valueAndExcepti } [TestFixture] + [Category("GameTest")] public class IsMouseVisible : ReadWritePropertyFixtureBase { public IsMouseVisible () : base (g => g.IsMouseVisible) @@ -172,6 +179,7 @@ public override void Cannot_set_illegal_value (Tuple valueAndExcepti } [TestFixture] + [Category("GameTest")] public class LaunchParameters_ : ReadOnlyPropertyFixtureBase { public LaunchParameters_ () : base (g => g.LaunchParameters) @@ -187,6 +195,7 @@ public void Is_available_before_Run () } [TestFixture] + [Category("GameTest")] public class Services : ReadOnlyPropertyFixtureBase { public Services () : base (g => g.Services) @@ -202,6 +211,7 @@ public void Is_available_before_Run () } [TestFixture] + [Category("GameTest")] public class TargetElapsedTime : ReadWritePropertyFixtureBase { public TargetElapsedTime () : base (g => g.TargetElapsedTime) @@ -218,6 +228,7 @@ public TargetElapsedTime () } [TestFixture] + [Category("GameTest")] public class Window : ReadOnlyPropertyFixtureBase { public Window () : base (g => g.Window) diff --git a/Tests/Framework/GameTest.cs b/Tests/Framework/GameTest.cs index 831dfa33ff7..8ef380af4a9 100644 --- a/Tests/Framework/GameTest.cs +++ b/Tests/Framework/GameTest.cs @@ -36,6 +36,7 @@ public virtual void TearDown () } [TestFixture] + [Category("GameTest")] public class Disposal : FixtureBase { [TestCase ("Components")] [TestCase ("Content")] @@ -130,6 +131,7 @@ private static void AssertDoesNotThrow (TestDelegate code) where T : Exceptio } [TestFixture] + [Category("GameTest")] public class Behaviors : FixtureBase { [Test, Ignore("Fix me!")] public void Nongraphical_run_succeeds () @@ -176,6 +178,7 @@ public void GameTickTest() } [TestFixture] + [Category("GameTest")] public class Misc { [Test] diff --git a/Tests/Framework/Graphics/BlendStateTest.cs b/Tests/Framework/Graphics/BlendStateTest.cs index 869e1add3fa..07168ba9e41 100644 --- a/Tests/Framework/Graphics/BlendStateTest.cs +++ b/Tests/Framework/Graphics/BlendStateTest.cs @@ -10,15 +10,18 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class BlendStateTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ShouldNotBeAbleToSetNullBlendState() { Assert.Throws(() => game.GraphicsDevice.BlendState = null); } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() { var blendState = new BlendState(); @@ -38,6 +41,7 @@ public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateDefaultStateObjects() { DoAsserts(BlendState.Additive, d => Assert.Throws(d)); @@ -83,6 +87,7 @@ private static void DoAsserts(BlendState blendState, Action assert #if DESKTOPGL [Ignore("Fails similarity test. Needs Investigating")] #endif + [RunOnUI] public void VisualTests() { var blends = new[] diff --git a/Tests/Framework/Graphics/DepthStencilStateTest.cs b/Tests/Framework/Graphics/DepthStencilStateTest.cs index bc3c4181ad9..013463bc495 100644 --- a/Tests/Framework/Graphics/DepthStencilStateTest.cs +++ b/Tests/Framework/Graphics/DepthStencilStateTest.cs @@ -11,15 +11,18 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class DepthStencilStateTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ShouldNotBeAbleToSetNullDepthStencilState() { Assert.Throws(() => gd.DepthStencilState = null); } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() { var depthStencilState = new DepthStencilState(); @@ -39,6 +42,7 @@ public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateDefaultStateObjects() { DoAsserts(DepthStencilState.Default, d => Assert.Throws(d)); @@ -68,6 +72,7 @@ private static void DoAsserts(DepthStencilState depthStencilState, Action( @@ -45,6 +48,7 @@ public void CtorAdapterNull() } [Test] + [RunOnUI] public void CtorPresentationParametersNull() { Assert.Throws( @@ -52,6 +56,7 @@ public void CtorPresentationParametersNull() } [Test] + [RunOnUI] public void DisposedWhenDisposingInvoked() { var count = 0; @@ -71,6 +76,7 @@ public void DisposedWhenDisposingInvoked() } [Test] + [RunOnUI] public void ResetDoesNotTriggerDeviceLost() { // TODO figure out exactly when a device is lost @@ -96,6 +102,7 @@ public void ResetDoesNotTriggerDeviceLost() } [Test] + [RunOnUI] public void ResetDoesNotClearState() { gd.RasterizerState = RasterizerState.CullNone; @@ -119,6 +126,7 @@ public void ResetDoesNotClearState() } [Test, Ignore("Make sure dynamic graphics resources are notified when graphics device is lost")] + [RunOnUI] public void ContentLostResources() { // https://blogs.msdn.microsoft.com/shawnhar/2007/12/12/virtualizing-the-graphicsdevice-in-xna-game-studio-2-0/ @@ -152,12 +160,14 @@ public void ContentLostResources() #if DESKTOPGL [Ignore("Does not throw the exception. Needs Investigating")] #endif + [RunOnUI] public void ResetWindowHandleNullThrowsException() { Assert.Throws(() => gd.Reset(new PresentationParameters())); } [Test] + [RunOnUI] public void Clear() { var colors = new Color [] { @@ -182,6 +192,7 @@ public void Clear() } [Test] + [RunOnUI] public void DrawPrimitivesParameterValidation() { var vertexBuffer = new VertexBuffer( @@ -216,6 +227,7 @@ public void DrawPrimitivesParameterValidation() } [Test] + [RunOnUI] public void DrawIndexedPrimitivesParameterValidation() { var vertexBuffer = new VertexBuffer( @@ -276,6 +288,7 @@ public void DrawIndexedPrimitivesParameterValidation() // This overload of DrawIndexedPrimitives is not supported on XNA. #if !XNA [Test] + [RunOnUI] public void DrawIndexedPrimitivesParameterValidation2() { var vertexBuffer = new VertexBuffer( @@ -327,6 +340,7 @@ public void DrawIndexedPrimitivesParameterValidation2() #if XNA || DIRECTX [Test] + [RunOnUI] public void DrawInstancedPrimitivesParameterValidation() { var vertexBuffer = new VertexBuffer( @@ -377,6 +391,7 @@ public void DrawInstancedPrimitivesParameterValidation() } [Test] + [RunOnUI] public void DrawInstancedPrimitivesVisualTest() { VertexBuffer vertexBuffer = null; @@ -456,6 +471,7 @@ public void DrawInstancedPrimitivesVisualTest() #endif [Test] + [RunOnUI] public void DrawUserPrimitivesParameterValidation() { var vertexDataNonEmpty = new[] @@ -505,6 +521,7 @@ private void DoDrawUserPrimitivesAsserts(VertexPositionColorTexture[] vertexData } [Test] + [RunOnUI] public void DrawUserIndexedPrimitivesParameterValidation() { var vertexDataNonEmpty = new[] @@ -597,6 +614,7 @@ private void DoDrawUserIndexedPrimitivesAsserts(VertexPositionColorTexture[] ver #if DESKTOPGL [Ignore("Vertex Textures are not implemented for OpenGL")] #endif + [RunOnUI] public void VertexTexturesGetSet() { // TODO: The availability of vertex textures should depend on GraphicsProfile. @@ -650,6 +668,7 @@ VertexDeclaration IVertexType.VertexDeclaration #if DESKTOPGL [Ignore("Vertex Textures are not implemented for OpenGL")] #endif + [RunOnUI] public void VertexTextureVisualTest() { // Implements an extremely simple terrain that reads from a heightmap in the vertex shader. @@ -721,6 +740,7 @@ public void VertexTextureVisualTest() #if DESKTOPGL [Ignore("Vertex samplers are not implemented for OpenGL")] #endif + [RunOnUI] public void VertexSamplerStatesGetSet() { var samplerState = new SamplerState { Filter = TextureFilter.Point }; @@ -733,6 +753,7 @@ public void VertexSamplerStatesGetSet() } [Test] + [RunOnUI] public void PresentInvalidOperationException() { // This should work else it means we had @@ -754,6 +775,7 @@ public void PresentInvalidOperationException() #if DESKTOPGL [Test] + [RunOnUI] public void DifferentVboGetsSet() { var vb1 = new VertexBuffer(gd, VertexPosition.VertexDeclaration, 6, BufferUsage.None); @@ -790,7 +812,9 @@ public void DifferentVboGetsSet() }; } + [Test] [TestCaseSource("BackBufferRects")] + [RunOnUI] public void GetBackBufferData(Rectangle? rectangle) { gd.Clear(Color.CornflowerBlue); diff --git a/Tests/Framework/Graphics/GraphicsDeviceTestFixtureBase.cs b/Tests/Framework/Graphics/GraphicsDeviceTestFixtureBase.cs index ad230a6cf8f..f8da1df78d1 100644 --- a/Tests/Framework/Graphics/GraphicsDeviceTestFixtureBase.cs +++ b/Tests/Framework/Graphics/GraphicsDeviceTestFixtureBase.cs @@ -3,6 +3,7 @@ // file 'LICENSE.txt', which is part of this source code package. using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,6 +14,7 @@ using MonoGame.Tests.Components; using MonoGame.Tests.Utilities; using NUnit.Framework; +using NUnit.Framework.Internal; namespace MonoGame.Tests.Graphics { @@ -162,7 +164,7 @@ protected void CheckFrames() { var referenceImageDirectory = Paths.ReferenceImage(folderName); var outputDirectory = Paths.CapturedFrame(folderName); var fileName = TestContext.CurrentContext.GetTestFrameFileNameFormat(_totalFramesExpected); - var capturedImagePath = Path.Combine(outputDirectory, fileName); + var capturedImagePath = Path.Combine(TestContext.CurrentContext.TestDirectory, outputDirectory, fileName); var referenceImagePath = Path.Combine(referenceImageDirectory, fileName); var allResults = new List(); diff --git a/Tests/Framework/Graphics/IndexBufferTest.cs b/Tests/Framework/Graphics/IndexBufferTest.cs index 72b052ca399..70eb4ade443 100644 --- a/Tests/Framework/Graphics/IndexBufferTest.cs +++ b/Tests/Framework/Graphics/IndexBufferTest.cs @@ -9,9 +9,11 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class IndexBufferTest: GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ShouldSetAndGetData() { var savedData = new short[] { 1, 2, 3, 4 }; @@ -26,6 +28,7 @@ public void ShouldSetAndGetData() } [Test] + [RunOnUI] public void ShouldSetAndGetData_elementCount() { var savedData = new short[] { 1, 2, 3, 4 }; @@ -43,6 +46,7 @@ public void ShouldSetAndGetData_elementCount() } [Test] + [RunOnUI] public void ShouldSetAndGetData_startIndex() { var savedData = new short[] { 1, 2, 3, 4 }; @@ -60,6 +64,7 @@ public void ShouldSetAndGetData_startIndex() } [Test] + [RunOnUI] public void ShouldSetAndGetData_offsetInBytes() { var savedData = new short[] { 1, 2, 3, 4 }; @@ -75,6 +80,7 @@ public void ShouldSetAndGetData_offsetInBytes() } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => diff --git a/Tests/Framework/Graphics/MiscellaneousTests.cs b/Tests/Framework/Graphics/MiscellaneousTests.cs index 5d70bcd093f..ed4661e550a 100644 --- a/Tests/Framework/Graphics/MiscellaneousTests.cs +++ b/Tests/Framework/Graphics/MiscellaneousTests.cs @@ -3,9 +3,12 @@ namespace MonoGame.Tests.Graphics { + [TestFixture] + [NonParallelizable] internal class MiscellaneousTests : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void Colored3DCube() { PrepareFrameCapture(); diff --git a/Tests/Framework/Graphics/ModelTest.cs b/Tests/Framework/Graphics/ModelTest.cs index 82be023a418..5c8d8b90211 100644 --- a/Tests/Framework/Graphics/ModelTest.cs +++ b/Tests/Framework/Graphics/ModelTest.cs @@ -13,6 +13,7 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal sealed class ModelTest : GraphicsDeviceTestFixtureBase { // model exported from default blender project. @@ -32,6 +33,7 @@ public void Initialize() } [Test] + [RunOnUI] public void ShouldDrawSampleModel() { // model contains a bit more that only the cube, so let extract the cube @@ -56,6 +58,7 @@ public void ShouldDrawSampleModel() } [Test] + [RunOnUI] public void MeshPartEffectReplacesOldOneOnParentModel() { // simple model used in test @@ -72,6 +75,7 @@ public void MeshPartEffectReplacesOldOneOnParentModel() #if !XNA // Tests below are valid for Monogame only because of manual model creation. [Test] + [RunOnUI] public void ShouldConstructAndInitialize() { var actual = new Model(gd, new List(), new List()); @@ -81,6 +85,7 @@ public void ShouldConstructAndInitialize() } [Test] + [RunOnUI] public void ShouldNotConstructWhenParamsAreNotValid() { // simple empty collections to make code more readable. @@ -94,6 +99,7 @@ public void ShouldNotConstructWhenParamsAreNotValid() } [Test] + [RunOnUI] public void ShouldReadTransformationsFromBones() { var someBones = new[] { new ModelBone(), new ModelBone() }.ToList(); @@ -110,6 +116,7 @@ public void ShouldReadTransformationsFromBones() } [Test] + [RunOnUI] public void CopyBoneTransformsFrom_Exceptions() { var someBones = new[] { new ModelBone() }.ToList(); @@ -120,6 +127,7 @@ public void CopyBoneTransformsFrom_Exceptions() } [Test] + [RunOnUI] public void CopyBoneTransformsTo_Exceptions() { var someBones = new[] { new ModelBone() }.ToList(); diff --git a/Tests/Framework/Graphics/OcclusionQueryTest.cs b/Tests/Framework/Graphics/OcclusionQueryTest.cs index 27bff99d13e..99a92f409cf 100644 --- a/Tests/Framework/Graphics/OcclusionQueryTest.cs +++ b/Tests/Framework/Graphics/OcclusionQueryTest.cs @@ -10,10 +10,12 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class OcclusionQueryTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ConstructorsAndProperties() { Assert.Throws(() => new OcclusionQuery(null)); @@ -30,6 +32,7 @@ public void ConstructorsAndProperties() } [Test] + [RunOnUI] public void MismatchedBeginEnd() { var occlusionQuery = new OcclusionQuery(gd); @@ -43,6 +46,7 @@ public void MismatchedBeginEnd() } [Test] + [RunOnUI] public void QueryOccludedSprites() { var spriteBatch = new SpriteBatch(gd); diff --git a/Tests/Framework/Graphics/RasterizerStateTest.cs b/Tests/Framework/Graphics/RasterizerStateTest.cs index 92a4b80bad2..202adddf6a6 100644 --- a/Tests/Framework/Graphics/RasterizerStateTest.cs +++ b/Tests/Framework/Graphics/RasterizerStateTest.cs @@ -11,6 +11,7 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class RasterizerStateTest : GraphicsDeviceTestFixtureBase { [TestCase(-1f)] @@ -20,6 +21,7 @@ internal class RasterizerStateTest : GraphicsDeviceTestFixtureBase [TestCase(1f)] #endif [TestCase(-0.0004f)] + [RunOnUI] public void DepthBiasVisualTest(float depthBias) { var effect = new BasicEffect(gd) @@ -65,12 +67,14 @@ public void DepthBiasVisualTest(float depthBias) } [Test] + [RunOnUI] public void ShouldNotBeAbleToSetNullRasterizerState() { Assert.Throws(() => gd.RasterizerState = null); } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() { var rasterizerState = new RasterizerState(); @@ -90,6 +94,7 @@ public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateDefaultStateObjects() { DoAsserts(RasterizerState.CullClockwise, d => Assert.Throws(d)); @@ -110,9 +115,11 @@ private static void DoAsserts(RasterizerState rasterizerState, Action(() => @@ -36,6 +39,7 @@ public void NullDeviceShouldThrowArgumentNullException() #if XNA [Ignore("XNA mipmaps fail our pixel comparison tests")] #endif + [RunOnUI] public void GenerateMips() { // Please note: @@ -113,6 +117,7 @@ public void GenerateMips() renderTarget.Dispose(); } + [Test] [TestCase(SurfaceFormat.Color, SurfaceFormat.Color)] // unsupported renderTarget formats [TestCase(SurfaceFormat.Alpha8, SurfaceFormat.Color)] @@ -127,6 +132,7 @@ public void GenerateMips() #endif [TestCase(SurfaceFormat.NormalizedByte2, SurfaceFormat.Color)] [TestCase(SurfaceFormat.NormalizedByte4, SurfaceFormat.Color)] + [RunOnUI] public void PreferredSurfaceFormatTest(SurfaceFormat preferredSurfaceFormat, SurfaceFormat expectedSurfaceFormat) { var renderTarget = new RenderTarget2D(gd, 16, 16, false, preferredSurfaceFormat, DepthFormat.None); @@ -135,6 +141,10 @@ public void PreferredSurfaceFormatTest(SurfaceFormat preferredSurfaceFormat, Sur } [Test] +#if DESKTOPGL + [Ignore ("Causes GL.GetError() returned 1282. Need to fix.")] +#endif + [RunOnUI] public void GetDataMSAA() { const int size = 100; @@ -157,8 +167,10 @@ public void GetDataMSAA() } #if DIRECTX + [Test] [TestCase(1)] [TestCase(2)] + [RunOnUI] public void GetSharedHandle(int preferredMultiSampleCount) { var rt = new RenderTarget2D(gd, 16, 16, false, SurfaceFormat.Color, DepthFormat.None, preferredMultiSampleCount, RenderTargetUsage.PlatformContents, true); diff --git a/Tests/Framework/Graphics/RenderTargetCubeTest.cs b/Tests/Framework/Graphics/RenderTargetCubeTest.cs index 304ab645b47..29c0bc1688a 100644 --- a/Tests/Framework/Graphics/RenderTargetCubeTest.cs +++ b/Tests/Framework/Graphics/RenderTargetCubeTest.cs @@ -10,9 +10,11 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class RenderTargetCubeTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ZeroSizeShouldFailTest() { RenderTargetCube renderTarget; @@ -20,6 +22,7 @@ public void ZeroSizeShouldFailTest() } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => @@ -30,9 +33,11 @@ public void NullDeviceShouldThrowArgumentNullException() GC.GetTotalMemory(true); // collect uninitialized renderTarget } + [Test] [TestCase(1)] [TestCase(8)] [TestCase(31)] + [RunOnUI] public void ShouldClearRenderTargetAndGetData(int size) { var dataSize = size * size; @@ -66,7 +71,8 @@ public void ShouldClearRenderTargetAndGetData(int size) renderTargetCube.Dispose(); } - + + [Test] [TestCase(SurfaceFormat.Color, SurfaceFormat.Color)] // unsupported renderTarget formats [TestCase(SurfaceFormat.Alpha8, SurfaceFormat.Color)] @@ -81,6 +87,7 @@ public void ShouldClearRenderTargetAndGetData(int size) #endif [TestCase(SurfaceFormat.NormalizedByte2, SurfaceFormat.Color)] [TestCase(SurfaceFormat.NormalizedByte4, SurfaceFormat.Color)] + [RunOnUI] public void PreferredSurfaceFormatTest(SurfaceFormat preferredSurfaceFormat, SurfaceFormat expectedSurfaceFormat) { var renderTarget = new RenderTargetCube(gd, 16, false, preferredSurfaceFormat, DepthFormat.None); diff --git a/Tests/Framework/Graphics/SamplerStateTest.cs b/Tests/Framework/Graphics/SamplerStateTest.cs index 64e619c6007..cf70e165e52 100644 --- a/Tests/Framework/Graphics/SamplerStateTest.cs +++ b/Tests/Framework/Graphics/SamplerStateTest.cs @@ -10,15 +10,18 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class SamplerStateTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ShouldNotBeAbleToSetNullSamplerState() { Assert.Throws(() => gd.SamplerStates[0] = null); } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() { var samplerState = new SamplerState(); @@ -38,6 +41,7 @@ public void ShouldNotBeAbleToMutateStateObjectAfterBindingToGraphicsDevice() } [Test] + [RunOnUI] public void ShouldNotBeAbleToMutateDefaultStateObjects() { DoAsserts(SamplerState.AnisotropicClamp, d => Assert.Throws(d)); @@ -67,6 +71,7 @@ private static void DoAsserts(SamplerState samplerState, Action as #if !XNA [Test] + [RunOnUI] public void VisualTestAddressModes() { PrepareFrameCapture(); @@ -125,6 +130,7 @@ public void VisualTestAddressModes() #if DESKTOPGL [Ignore("Comparison samplers are ps_4_0 and up, cannot use them on DesktopGL due to MojoShader")] #endif + [RunOnUI] public void VisualTestComparisonFunction() { PrepareFrameCapture(); diff --git a/Tests/Framework/Graphics/ScissorRectangleTest.cs b/Tests/Framework/Graphics/ScissorRectangleTest.cs index 24fe20847d6..e85dc72637c 100644 --- a/Tests/Framework/Graphics/ScissorRectangleTest.cs +++ b/Tests/Framework/Graphics/ScissorRectangleTest.cs @@ -1,10 +1,14 @@ +using System.Threading; +using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using NUnit.Framework; +using NUnit.Framework.Internal; namespace MonoGame.Tests.Graphics { [TestFixture] + internal class ScissorRectangleTest : GraphicsDeviceTestFixtureBase { private SpriteBatch _spriteBatch; @@ -41,6 +45,8 @@ public override void TearDown() } [Test] + [Ignore ("Fails Investigate?")] + [RunOnUI] public void Draw_with_scissor_rect() { PrepareFrameCapture(); @@ -69,6 +75,7 @@ public void Draw_with_scissor_rect() } [Test] + [RunOnUI] public void Draw_with_render_target_change() { PrepareFrameCapture(); @@ -85,6 +92,7 @@ public void Draw_with_render_target_change() } [Test] + [RunOnUI] public void Draw_without_render_target_change() { PrepareFrameCapture(); diff --git a/Tests/Framework/Graphics/ShaderTest.cs b/Tests/Framework/Graphics/ShaderTest.cs index cd9269225ee..8040409616c 100644 --- a/Tests/Framework/Graphics/ShaderTest.cs +++ b/Tests/Framework/Graphics/ShaderTest.cs @@ -10,8 +10,10 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class ShaderTest : GraphicsDeviceTestFixtureBase { + [Test] [TestCase("NoEffect")] [TestCase("HighContrast")] [TestCase("Bevels")] @@ -23,6 +25,7 @@ class ShaderTest : GraphicsDeviceTestFixtureBase // TODO this does not render for some reason, we need to fix this [TestCase("RainbowH")] #endif + [RunOnUI] public void Shader(string effectName) { PrepareFrameCapture(); diff --git a/Tests/Framework/Graphics/SpriteBatchTest.cs b/Tests/Framework/Graphics/SpriteBatchTest.cs index 6ac752c5aea..008b03fab94 100644 --- a/Tests/Framework/Graphics/SpriteBatchTest.cs +++ b/Tests/Framework/Graphics/SpriteBatchTest.cs @@ -3,12 +3,14 @@ // file 'LICENSE.txt', which is part of this source code package. using System; +using System.Threading; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using NUnit.Framework; namespace MonoGame.Tests.Graphics { - [TestFixture] + [TestFixture] + [NonParallelizable] class SpriteBatchTest : GraphicsDeviceTestFixtureBase { private SpriteBatch _spriteBatch; private Texture2D _texture; @@ -50,6 +52,7 @@ public override void TearDown() } [Test] + [RunOnUI] public void BeginCalledTwiceThrows() { _spriteBatch.Begin(); @@ -57,12 +60,14 @@ public void BeginCalledTwiceThrows() } [Test] + [RunOnUI] public void BeginNotCalledThrows() { Assert.Throws(() => _spriteBatch.End()); } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => @@ -74,6 +79,7 @@ public void NullDeviceShouldThrowArgumentNullException() } [Test] + [RunOnUI] public void Draw_without_blend () { PrepareFrameCapture(); @@ -86,6 +92,7 @@ public void Draw_without_blend () } [Test] + [RunOnUI] public void Draw_with_additive_blend () { PrepareFrameCapture(); @@ -99,6 +106,7 @@ public void Draw_with_additive_blend () } [Test] + [RunOnUI] public void Draw_normal () { PrepareFrameCapture(); @@ -114,6 +122,7 @@ public void Draw_normal () [TestCase(1.5f, 1.5f)] [TestCase(0.75f, 2.0f)] [TestCase(1.25f, 0.8f)] + [RunOnUI] public void Draw_stretched (float xScale, float yScale) { PrepareFrameCapture(); @@ -131,6 +140,7 @@ public void Draw_stretched (float xScale, float yScale) [TestCase("Red")] [TestCase("GreenYellow")] [TestCase("Teal")] + [RunOnUI] public void Draw_with_filter_color (string colorName) { var color = colorName.ToColor (); @@ -147,6 +157,7 @@ public void Draw_with_filter_color (string colorName) [TestCase (1.41f)] [TestCase (2.17f)] [TestCase (2.81f)] + [RunOnUI] public void Draw_rotated (float rotation) { PrepareFrameCapture(); @@ -164,6 +175,7 @@ public void Draw_rotated (float rotation) } [Test] + [RunOnUI] public void Draw_with_source_rect () { PrepareFrameCapture(); @@ -180,6 +192,7 @@ public void Draw_with_source_rect () [TestCase(10, 10, 40, 40)] [TestCase(30, 30, 30, 50)] [TestCase(20, 30, 80, 60)] + [RunOnUI] public void Draw_with_source_and_dest_rect (int x, int y, int width, int height) { PrepareFrameCapture(); @@ -196,6 +209,7 @@ public void Draw_with_source_and_dest_rect (int x, int y, int width, int height) [TestCase("Red", 120)] [TestCase("White", 80)] [TestCase("GreenYellow", 200)] + [RunOnUI] public void Draw_with_alpha_blending (string colorName, byte alpha) { PrepareFrameCapture(); @@ -214,6 +228,7 @@ public void Draw_with_alpha_blending (string colorName, byte alpha) [TestCase (SpriteEffects.FlipHorizontally)] [TestCase (SpriteEffects.FlipVertically)] [TestCase (SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically)] + [RunOnUI] public void Draw_with_SpriteEffects (SpriteEffects effects) { PrepareFrameCapture(); @@ -240,6 +255,7 @@ public void Draw_with_SpriteEffects (SpriteEffects effects) // in directly results in an enormous test name (and captured // image filename). [Test] + [RunOnUI] public void Draw_with_matrix ([Range(0, 4)]int matrixIndex) { PrepareFrameCapture(); @@ -263,6 +279,7 @@ public void Draw_with_matrix ([Range(0, 4)]int matrixIndex) // Disabled on XNA because the sorting algorithm is probably different [TestCase(SpriteSortMode.Texture)] #endif + [RunOnUI] public void Draw_with_SpriteSortMode(SpriteSortMode sortMode) { Similarity = 0.995f; @@ -297,6 +314,7 @@ public void Draw_with_SpriteSortMode(SpriteSortMode sortMode) //_spriteBatch.GraphicsDevice.RasterizerState.ScissorTestEnable = false; [Test] + [RunOnUI] public void DrawRequiresTexture() { _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque); @@ -305,6 +323,7 @@ public void DrawRequiresTexture() } [Test] + [RunOnUI] public void DrawWithTexture() { Assert.That(gd.Textures[0], Is.Null); @@ -317,6 +336,7 @@ public void DrawWithTexture() } [Test] + [RunOnUI] public void DrawWithCustomEffectAndTwoTextures() { var customSpriteEffect = AssetTestUtility.LoadEffect(content, "CustomSpriteBatchEffect"); @@ -337,6 +357,7 @@ public void DrawWithCustomEffectAndTwoTextures() } [Test] + [RunOnUI] public void DrawWithLayerDepth() { PrepareFrameCapture(); @@ -416,6 +437,7 @@ public void DrawWithLayerDepth() // There are possibly also some differences because of how rasterization is handled. [Ignore("OpenGL produces a slightly different result")] #endif + [RunOnUI] public void Draw_many() { PrepareFrameCapture(); @@ -431,6 +453,7 @@ public void Draw_many() [TestCase(SpriteSortMode.Deferred)] [TestCase(SpriteSortMode.Immediate)] + [RunOnUI] public void Draw_with_viewport_changing(SpriteSortMode sortMode) { Similarity = 0.975f; diff --git a/Tests/Framework/Graphics/SpriteFontTest.cs b/Tests/Framework/Graphics/SpriteFontTest.cs index 929e744e4f3..c7badd9fdd1 100644 --- a/Tests/Framework/Graphics/SpriteFontTest.cs +++ b/Tests/Framework/Graphics/SpriteFontTest.cs @@ -10,6 +10,7 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class SpriteFontTest : GraphicsDeviceTestFixtureBase { private SpriteBatch _spriteBatch; @@ -33,6 +34,7 @@ public override void TearDown() base.TearDown(); } + [Test] [TestCase("Default", "The quick brown fox jumps over the lazy dog. 1234567890", 605, 21)] [TestCase("Default", "The quick brown fox jumps\nover the lazy dog.\n1234567890", 275, 59)] [TestCase("Default", "The quick brown fox jumps over the lazy dog.\r1234567890", 594, 21)] @@ -57,6 +59,7 @@ public override void TearDown() [TestCase("SegoeKeycaps", "The quick brown fox jumps over the lazy dog. 1234567890", 988, 20)] [TestCase("SegoeKeycaps", "The quick brown fox jumps\nover the lazy dog.\n1234567890", 448, 58)] [TestCase("SegoeKeycaps", "!", 16, 20)] // LSB=1, W=15, RSB=0 + [RunOnUI] public void MeasureString_returns_correct_values(string fontName, string text, float width, float height) { var font = game.Content.Load(Paths.Font(fontName)); @@ -66,6 +69,7 @@ public void MeasureString_returns_correct_values(string fontName, string text, f } [Test] + [RunOnUI] public void Plain () { PrepareFrameCapture(); @@ -83,6 +87,7 @@ public void Plain () } [Test] + [RunOnUI] public void Rotated () { PrepareFrameCapture(); @@ -108,6 +113,7 @@ public void Rotated () } [Test] + [RunOnUI] public void Scaled () { PrepareFrameCapture(); @@ -132,9 +138,11 @@ public void Scaled () CheckFrames(); } + [Test] [TestCase(SpriteEffects.FlipHorizontally)] [TestCase(SpriteEffects.FlipVertically)] [TestCase(SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically)] + [RunOnUI] public void Draw_with_SpriteEffects (SpriteEffects effects) { PrepareFrameCapture(); @@ -160,6 +168,7 @@ public void Draw_with_SpriteEffects (SpriteEffects effects) } [Test] + [RunOnUI] public void Origins_rotated () { PrepareFrameCapture(); @@ -209,6 +218,7 @@ public void Origins_rotated () } [Test] + [RunOnUI] public void Origins_scaled () { PrepareFrameCapture(); @@ -258,6 +268,7 @@ public void Origins_scaled () } [Test] + [RunOnUI] public void Draw_with_LayerDepth() { PrepareFrameCapture(); @@ -397,6 +408,7 @@ public void Draw_with_LayerDepth() } [Test] + [RunOnUI] public void Hullabaloo () { PrepareFrameCapture(); @@ -412,6 +424,7 @@ public void Hullabaloo () } [Test] + [RunOnUI] public void Hullabaloo2 () { PrepareFrameCapture(); @@ -426,7 +439,7 @@ public void Hullabaloo2 () CheckFrames(); } - + [Test] [TestCase("The quick brown fox jumps over the lazy dog. 1234567890", TestName = "Multiline_noNewline")] [TestCase("The quick brown fox jumps\nover the lazy dog.\n1234567890", TestName = "Multiline_Newline")] [TestCase("The quick brown fox jumps over the lazy dog.\r1234567890", TestName = "Multiline_CarriageReturn")] @@ -436,6 +449,7 @@ So he wrote a routine To ask 'What's it all mean?' But the answer was still '42'. R Humphries, Sutton Coldfield", TestName = "Multiline_verbatimString")] + [RunOnUI] public void Multiline (string text) { PrepareFrameCapture(); @@ -478,6 +492,7 @@ public void Multiline (string text) } [Test] + [RunOnUI] public void Font_spacing_is_respected () { PrepareFrameCapture(); @@ -504,9 +519,11 @@ public void Font_spacing_is_respected () CheckFrames(); } + [Test] [TestCase("The rain in España stays mainly in the plain - now in français")] [TestCase("\x1f")] [TestCase("\x7f")] + [RunOnUI] public void Throws_when_drawing_unavailable_characters(string text) { _spriteBatch.Begin (); @@ -515,18 +532,22 @@ public void Throws_when_drawing_unavailable_characters(string text) _spriteBatch.End (); } + [Test] [TestCase('ñ')] [TestCase((char)127)] [TestCase((char)31)] + [RunOnUI] public void Throws_when_setting_unavailable_DefaultCharacter(char character) { Assert.Throws (() => _defaultFont.DefaultCharacter = character); } + [Test] [TestCase((char)32)] [TestCase((char)63)] [TestCase((char)126)] + [RunOnUI] public void Does_not_throw_when_setting_available_DefaultCharacter(char character) { Assert.DoesNotThrow(() => _defaultFont.DefaultCharacter = character); diff --git a/Tests/Framework/Graphics/Texture2DNonVisualTest.cs b/Tests/Framework/Graphics/Texture2DNonVisualTest.cs index a5cc5d160e8..5d7ee4b880c 100644 --- a/Tests/Framework/Graphics/Texture2DNonVisualTest.cs +++ b/Tests/Framework/Graphics/Texture2DNonVisualTest.cs @@ -13,10 +13,12 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] internal class Texture2DNonVisualTest : GraphicsDeviceTestFixtureBase { Texture2D _texture; + [Test] #if !XNA [TestCase("Assets/Textures/LogoOnly_64px.bmp")] [TestCase("Assets/Textures/LogoOnly_64px.tga")] @@ -29,6 +31,7 @@ internal class Texture2DNonVisualTest : GraphicsDeviceTestFixtureBase [TestCase("Assets/Textures/24bit.png")] [TestCase("Assets/Textures/32bit.png")] [TestCase("Assets/Textures/sample_1280x853.hdr")] + [RunOnUI] public void FromStreamShouldWorkTest(string filename) { using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) @@ -47,6 +50,7 @@ public void FromStreamShouldWorkTest(string filename) _texture = null; } + [Test] #if XNA [TestCase("Assets/Textures/LogoOnly_64px.bmp")] #endif @@ -54,6 +58,7 @@ public void FromStreamShouldWorkTest(string filename) [TestCase("Assets/Textures/LogoOnly_64px.tif")] [TestCase("Assets/Textures/LogoOnly_64px.dds")] [TestCase("Assets/Textures/SampleCube64DXT1Mips.dds")] + [RunOnUI] public void FromStreamShouldFailTest(string filename) { using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) @@ -63,6 +68,7 @@ public void FromStreamShouldFailTest(string filename) } [Test] + [RunOnUI] public void FromStreamArgumentNullTest() { Assert.Throws(() => Texture2D.FromStream(gd, (Stream) null)); @@ -73,6 +79,7 @@ public void FromStreamArgumentNullTest() } [Test] + [RunOnUI] public void FromStreamCustomProcessor() { // This test sets the color of every other color to custom color @@ -123,7 +130,8 @@ public void FromStreamCustomProcessor() } } - [TestCase] + [Test] + [RunOnUI] public void FromStreamNotPremultiplied() { // XNA will not try to premultiply your image on @@ -148,7 +156,8 @@ public void FromStreamNotPremultiplied() } } - [TestCase] + [Test] + [RunOnUI] public void FromStreamAtTheEnd() { // Check whether texture can be loaded if a stream being at its end @@ -177,7 +186,8 @@ public void FromStreamAtTheEnd() } } - [TestCase] + [Test] + [RunOnUI] public void FromStreamBlackAlpha() { // XNA will make any pixel with an alpha value @@ -203,6 +213,7 @@ public void FromStreamBlackAlpha() } [Test] + [RunOnUI] public void ZeroSizeShouldFailTest() { Texture2D texture; @@ -212,6 +223,7 @@ public void ZeroSizeShouldFailTest() } [Test] + [RunOnUI] public void SimpleGetSetDataTest() { using (var tex = new Texture2D(gd, 4, 4, false, SurfaceFormat.Color)) @@ -237,6 +249,7 @@ public void SimpleGetSetDataTest() } } + [Test] [TestCase(25, 23, 1, 1, 0, 1)] [TestCase(25, 23, 1, 1, 1, 1)] [TestCase(25, 23, 2, 1, 0, 2)] @@ -245,6 +258,7 @@ public void SimpleGetSetDataTest() [TestCase(25, 23, 1, 2, 1, 2)] [TestCase(25, 23, 2, 2, 0, 4)] [TestCase(25, 23, 2, 2, 1, 4)] + [RunOnUI] public void PlatformGetDataWithOffsetTest(int rx, int ry, int rw, int rh, int startIndex, int elementsToRead) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -265,8 +279,10 @@ public void PlatformGetDataWithOffsetTest(int rx, int ry, int rw, int rh, int st t.Dispose(); } } + [Test] [TestCase(25, 23, 2, 2, 0, 2)] [TestCase(25, 23, 2, 2, 1, 2)] + [RunOnUI] public void GetDataException(int rx, int ry, int rw, int rh, int startIndex, int elementsToRead) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -284,7 +300,9 @@ public void GetDataException(int rx, int ry, int rw, int rh, int startIndex, int } } + [Test] [TestCase(4096)] + [RunOnUI] public void SetData1ParameterGoodTest(int arraySize) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -322,10 +340,12 @@ public void SetData1ParameterGoodTest(int arraySize) } } + [Test] [TestCase(2000)] [TestCase(4095)] [TestCase(2000000)] [TestCase(4097)] + [RunOnUI] public void SetData1ParameterExceptionTest(int arraySize) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -352,6 +372,7 @@ public void SetData1ParameterExceptionTest(int arraySize) } } + [Test] [TestCase(SurfaceFormat.HalfSingle, (short)(160 << 8 + 120))] #if !DESKTOPGL // format not supported @@ -364,6 +385,7 @@ public void SetData1ParameterExceptionTest(int arraySize) [TestCase(SurfaceFormat.Single, (byte)150)] [TestCase(SurfaceFormat.Single, (short)(160 << 8 + 120))] [TestCase(SurfaceFormat.Single, (float)(200 << 24 + 180 << 16 + 160 << 8 + 120))] + [RunOnUI] public void SetDataFormatTest(SurfaceFormat format, TBuffer value) where TBuffer : struct { const int textureSize = 16; @@ -390,8 +412,10 @@ public void SetDataFormatTest(SurfaceFormat format, TBuffer value) wher t.Dispose(); } + [Test] [TestCase(SurfaceFormat.Color, (long)0)] [TestCase(SurfaceFormat.HalfSingle, (float)0)] + [RunOnUI] public void SetDataFormatFailingTestTBufferTooLarge(SurfaceFormat format, TBuffer value) where TBuffer : struct { const int textureSize = 16; @@ -413,6 +437,7 @@ public void SetDataFormatFailingTestTBufferTooLarge(SurfaceFormat forma } [Test] + [RunOnUI] public void SetDataFormatFailingTestModTBufferNotZero() { const int textureSize = 12; @@ -455,10 +480,12 @@ public static int GetFormatSize(SurfaceFormat surfaceFormat) } } + [Test] [TestCase(4200, 0, 4096)] [TestCase(4097, 1, 4096)] [TestCase(4097, 0, 4096)] [TestCase(4096, 0, 4096)] + [RunOnUI] public void SetData3ParameterGoodTest(int arraySize, int startIndex, int elements) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -496,6 +523,7 @@ public void SetData3ParameterGoodTest(int arraySize, int startIndex, int element } } + [Test] [TestCase(2000, 0, 4096)] [TestCase(4095, 0, 4095)] [TestCase(4095, 1, 4095)] @@ -509,6 +537,7 @@ public void SetData3ParameterGoodTest(int arraySize, int startIndex, int element [TestCase(4098, 1, 4097)] [TestCase(4097, 0, 4097)] [TestCase(4096, 0, 4095)] + [RunOnUI] public void SetData3ParameterExceptionTest(int arraySize, int startIndex, int elements) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -536,6 +565,7 @@ public void SetData3ParameterExceptionTest(int arraySize, int startIndex, int el } } + [Test] [TestCase(4096, 0, 4096, 0, 0, 64, 64)] [TestCase(4096, 0, 3969, 1, 1, 63, 63)] [TestCase(3969, 0, 3969, 1, 1, 63, 63)] @@ -543,6 +573,7 @@ public void SetData3ParameterExceptionTest(int arraySize, int startIndex, int el [TestCase(4097, 1, 3969, 1, 1, 63, 63)] [TestCase(3970, 1, 3969, 1, 1, 63, 63)] [TestCase(4097, 1, 4096, 0, 0, 64, 64)] + [RunOnUI] public void SetData5ParameterGoodTest(int arraySize, int startIndex, int elements, int x, int y, int w, int h) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -582,6 +613,7 @@ public void SetData5ParameterGoodTest(int arraySize, int startIndex, int element t.Dispose(); } } + [Test] [TestCase(3844, 0, 3844, 1, 1, 63, 63)] [TestCase(3845, 1, 3844, 1, 1, 63, 63)] [TestCase(3969, 0, 4096, 1, 1, 63, 63)] @@ -594,6 +626,7 @@ public void SetData5ParameterGoodTest(int arraySize, int startIndex, int element [TestCase(4097, 1, 4095, 0, 0, 64, 64)] [TestCase(4097, 1, 3844, 1, 1, 63, 63)] [TestCase(3970, 1, 4096, 1, 1, 63, 63)] + [RunOnUI] public void SetData5ParameterExceptionTest(int arraySize, int startIndex, int elements, int x, int y, int w, int h) { using (System.IO.StreamReader reader = new System.IO.StreamReader("Assets/Textures/LogoOnly_64px.png")) @@ -624,6 +657,7 @@ public void SetData5ParameterExceptionTest(int arraySize, int startIndex, int el } [Test] + [RunOnUI] public void GetDataNegativeOrZeroRectWidthAndHeightThrows() { using (var t = new Texture2D(gd, 10, 10)) @@ -641,6 +675,7 @@ public void GetDataNegativeOrZeroRectWidthAndHeightThrows() } [Test] + [RunOnUI] public void GetAndSetDataDxtCompressed() { var t = content.Load(Paths.Texture ("random_16px_dxt")); @@ -694,6 +729,7 @@ public void GetAndSetDataDxtCompressed() #if DESKTOPGL [Ignore("PlatformGetData fails under OpenGL!")] #endif + [RunOnUI] public void LoadOddSizedDxtCompressed() { // This is testing that DXT compressed mip levels that @@ -732,12 +768,14 @@ public void LoadOddSizedDxtCompressed() t.Dispose(); } + [Test] // DXT1 [TestCase(8, "random_16px_dxt", 0)] [TestCase(8, "random_16px_dxt", 1)] // DXT5 [TestCase(16, "random_16px_dxt_alpha", 0)] [TestCase(16, "random_16px_dxt_alpha", 1)] + [RunOnUI] public void GetAndSetDataDxtNotMultipleOf4Rounding(int bs, string texName, int mip) { var t = content.Load(Paths.Texture (texName)); @@ -786,8 +824,10 @@ public void GetAndSetDataDxtNotMultipleOf4Rounding(int bs, string texName, int m t.Dispose(); } + [Test] [TestCase("random_16px_dxt", 8)] [TestCase("random_16px_dxt_alpha", 16)] + [RunOnUI] public void GetAndSetDataDxtDontRoundWhenOutsideBounds(string texName, int bs) { var t = content.Load(Paths.Texture(texName)); @@ -802,8 +842,10 @@ public void GetAndSetDataDxtDontRoundWhenOutsideBounds(string texName, int bs) t.Dispose(); } + [Test] [TestCase("random_16px_dxt", 8)] [TestCase("random_16px_dxt_alpha", 16)] + [RunOnUI] public void GetAndSetDataDxtLowerMips(string texName, int bs) { var t = content.Load(Paths.Texture(texName)); @@ -826,6 +868,7 @@ public void GetAndSetDataDxtLowerMips(string texName, int bs) } [Test] + [RunOnUI] public void GetDataRowPitch() { const int w = 5; @@ -845,6 +888,7 @@ public void GetDataRowPitch() } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => diff --git a/Tests/Framework/Graphics/Texture2DTest.cs b/Tests/Framework/Graphics/Texture2DTest.cs index 55462ef4bed..d8c1c8f5652 100644 --- a/Tests/Framework/Graphics/Texture2DTest.cs +++ b/Tests/Framework/Graphics/Texture2DTest.cs @@ -9,11 +9,14 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class Texture2DTest : GraphicsDeviceTestFixtureBase { + [Test] [TestCase(1, 1)] [TestCase(8, 8)] [TestCase(31, 7)] + [RunOnUI] public void ShouldSetAndGetData(int width, int height) { var dataSize = width * height; @@ -30,9 +33,11 @@ public void ShouldSetAndGetData(int width, int height) texture2D.Dispose(); } + [Test] [TestCase(1, 1)] [TestCase(8, 8)] [TestCase(31, 7)] + [RunOnUI] public void ShouldSetAndGetDataForLevel(int width, int height) { var texture2D = new Texture2D(gd, width, height, true, SurfaceFormat.Color); @@ -56,6 +61,7 @@ public void ShouldSetAndGetDataForLevel(int width, int height) } [Test] + [RunOnUI] public void ShouldGetDataFromRectangle() { const int dataSize = 128 * 128; @@ -80,10 +86,12 @@ public void ShouldGetDataFromRectangle() } #if DIRECTX + [Test] [TestCase(SurfaceFormat.Color, false)] [TestCase(SurfaceFormat.Color, true)] [TestCase(SurfaceFormat.ColorSRgb, false)] [TestCase(SurfaceFormat.ColorSRgb, true)] + [RunOnUI] public void DrawWithSRgbFormats(SurfaceFormat textureFormat, bool sRgbSourceTexture) { PrepareFrameCapture(); @@ -134,12 +142,14 @@ public void DrawWithSRgbFormats(SurfaceFormat textureFormat, bool sRgbSourceText #endif #if !XNA + [Test] [TestCase(1, 1)] [TestCase(8, 8)] [TestCase(31, 7)] #if DESKTOPGL [Ignore("Not yet implemented in OpenGL")] #endif + [RunOnUI] public void ShouldSetAndGetDataForTextureArray(int width, int height) { const int arraySize = 4; @@ -167,6 +177,7 @@ public void ShouldSetAndGetDataForTextureArray(int width, int height) #if DIRECTX [Test] + [RunOnUI] public void TextureArrayAsRenderTargetAndShaderResource() { PrepareFrameCapture(); @@ -223,6 +234,7 @@ public void TextureArrayAsRenderTargetAndShaderResource() #endif [Test] + [RunOnUI] public void SetDataRowPitch() { PrepareFrameCapture(); diff --git a/Tests/Framework/Graphics/Texture3DNonVisualTest.cs b/Tests/Framework/Graphics/Texture3DNonVisualTest.cs index 8dcac919cb1..69c6abc798f 100644 --- a/Tests/Framework/Graphics/Texture3DNonVisualTest.cs +++ b/Tests/Framework/Graphics/Texture3DNonVisualTest.cs @@ -9,10 +9,11 @@ namespace MonoGame.Tests.Graphics { -#if !WINDOWS +#if DESKTOPGL [Ignore("Texture3D is not implemented for the OpenGL backend.")] #endif [TestFixture] + [NonParallelizable] public class Texture3DNonVisualTest { Texture3D t; @@ -53,6 +54,7 @@ public void TestSetUp() } [Test] + [RunOnUI] public void ZeroSizeShouldFailTest() { Texture3D texture; @@ -67,6 +69,7 @@ public void ZeroSizeShouldFailTest() } [Test] + [RunOnUI] public void SetData1ParameterTest() { Color[] written = new Color[a]; @@ -74,9 +77,11 @@ public void SetData1ParameterTest() Assert.AreEqual(reference, written); } + [Test] [TestCase(a, 0, a)] [TestCase(a + 1, 0, a)] [TestCase(a + 1, 1, a)] + [RunOnUI] public void SetData3ParametersSuccessTest(int arrayLength, int startIndex, int elementCount) { Color[] write = new Color[arrayLength]; @@ -99,11 +104,13 @@ public void SetData3ParametersSuccessTest(int arrayLength, int startIndex, int e } + [Test] [TestCase(a, 0, a - 1)] [TestCase(a - 1, 0, a)] [TestCase(a, 1, a)] [TestCase(a, 0, a + 1)] [TestCase(a + 1, 1, a + 1)] + [RunOnUI] public void SetData3ParametersExceptionTest(int arrayLength, int startIndex, int elementCount) { Color[] write = new Color[arrayLength]; @@ -115,9 +122,11 @@ public void SetData3ParametersExceptionTest(int arrayLength, int startIndex, int Assert.Throws(Is.InstanceOf(), () =>t.SetData(write, startIndex, elementCount)); } + [Test] [TestCase((w - 2) * (h - 2) * (d - 2), 0, (w - 2) * (h - 2) * (d - 2), 1, 1, 1, w - 2, h - 2, d - 2)] [TestCase(a, 0, a, 0, 0, 0, w, h, d)] [TestCase(a + 1, 1, a, 0, 0, 0, w, h, d)] + [RunOnUI] public void SetData9ParametersSuccessTest(int arrayLength, int startIndex, int elementCount, int x, int y, int z, int w, int h, int d) { Color[] write = new Color[arrayLength]; @@ -141,8 +150,10 @@ public void SetData9ParametersSuccessTest(int arrayLength, int startIndex, int e } } + [Test] [TestCase(a, 0, a, -1, -1, -1, w + 1, h + 1, d + 1)] [TestCase(a, 1, a, 0, 0, 0, w, h, d)] + [RunOnUI] public void SetData9ParametersExceptionTest(int arrayLength, int startIndex, int elementCount, int x, int y, int z, int w, int h, int d) { Color[] write = new Color[arrayLength]; @@ -154,6 +165,7 @@ public void SetData9ParametersExceptionTest(int arrayLength, int startIndex, int } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => diff --git a/Tests/Framework/Graphics/Texture3DTest.cs b/Tests/Framework/Graphics/Texture3DTest.cs index aa06d3a2058..d0c49d3f7bc 100644 --- a/Tests/Framework/Graphics/Texture3DTest.cs +++ b/Tests/Framework/Graphics/Texture3DTest.cs @@ -7,15 +7,18 @@ namespace MonoGame.Tests.Graphics { -#if !WINDOWS +#if DESKTOPGL [Ignore("Texture3D is not implemented for the OpenGL backend.")] #endif [TestFixture] + [NonParallelizable] class Texture3DTest : GraphicsDeviceTestFixtureBase { + [Test] [TestCase(1, 1, 1)] [TestCase(8, 8, 8)] [TestCase(31, 7, 13)] + [RunOnUI] public void ShouldSetAndGetData(int width, int height, int depth) { var dataSize = width * height * depth; diff --git a/Tests/Framework/Graphics/TextureCubeTest.cs b/Tests/Framework/Graphics/TextureCubeTest.cs index e9d3300da64..9e21da6e11b 100644 --- a/Tests/Framework/Graphics/TextureCubeTest.cs +++ b/Tests/Framework/Graphics/TextureCubeTest.cs @@ -10,18 +10,22 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class TextureCubeTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void ZeroSizeShouldFailTest() { TextureCube texture; Assert.Throws(() => texture = new TextureCube(gd, 0, false, SurfaceFormat.Color)); } + [Test] [TestCase(1)] [TestCase(8)] [TestCase(31)] + [RunOnUI] public void ShouldSetAndGetData(int size) { var dataSize = size * size; @@ -44,6 +48,7 @@ public void ShouldSetAndGetData(int size) } [Test] + [RunOnUI] public void GetAndSetDataDxtCompressed() { var t = content.Load(Paths.Texture ("SampleCube64DXT1Mips")); @@ -97,9 +102,11 @@ public void GetAndSetDataDxtCompressed() t.Dispose(); } + [Test] // DXT1 [TestCase(8, "SampleCube64DXT1Mips", 0)] [TestCase(8, "SampleCube64DXT1Mips", 1)] + [RunOnUI] // TODO DXT5 //[TestCase(16, "SampleCube64DXT5Mips", 0)] //[TestCase(16, "SampleCube64DXT5Mips", 1)] @@ -155,8 +162,10 @@ public void GetAndSetDataDxtNotMultipleOf4Rounding(int bs, string texName, int m t.Dispose(); } + [Test] [TestCase("SampleCube64DXT1Mips", 8)] //[TestCase("SampleCube64DXT5Mips", 16)] + [RunOnUI] public void GetAndSetDataDxtDontRoundWhenOutsideBounds(string texName, int bs) { var t = content.Load(Paths.Texture(texName)); @@ -175,8 +184,10 @@ public void GetAndSetDataDxtDontRoundWhenOutsideBounds(string texName, int bs) t.Dispose(); } + [Test] [TestCase("SampleCube64DXT1Mips", 8)] //[TestCase("SampleCube64DXT5Mips", 16)] + [RunOnUI] public void GetAndSetDataDxtLowerMips(string texName, int bs) { var t = content.Load(Paths.Texture(texName)); @@ -203,6 +214,7 @@ public void GetAndSetDataDxtLowerMips(string texName, int bs) } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => diff --git a/Tests/Framework/Graphics/VertexBufferTest.cs b/Tests/Framework/Graphics/VertexBufferTest.cs index 4a8b72667b0..edce1bcb57a 100644 --- a/Tests/Framework/Graphics/VertexBufferTest.cs +++ b/Tests/Framework/Graphics/VertexBufferTest.cs @@ -12,6 +12,7 @@ namespace MonoGame.Tests.Graphics { [TestFixture] + [NonParallelizable] class VertexBufferTest : GraphicsDeviceTestFixtureBase { VertexPositionTexture[] savedData = new VertexPositionTexture[] @@ -23,8 +24,10 @@ class VertexBufferTest : GraphicsDeviceTestFixtureBase }; VertexPositionTexture vertexZero = new VertexPositionTexture(Vector3.Zero, Vector2.Zero); + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void ShouldSetAndGetData(bool dynamic) { var vertexBuffer = (dynamic) @@ -39,8 +42,10 @@ public void ShouldSetAndGetData(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void ShouldSetAndGetData_elementCount(bool dynamic) { var vertexBuffer = (dynamic) @@ -58,8 +63,10 @@ public void ShouldSetAndGetData_elementCount(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void ShouldSetAndGetData_startIndex(bool dynamic) { var vertexBuffer = (dynamic) @@ -77,8 +84,10 @@ public void ShouldSetAndGetData_startIndex(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void ShouldSetAndGetData_offsetInBytes(bool dynamic) { var vertexBuffer = (dynamic) @@ -96,8 +105,10 @@ public void ShouldSetAndGetData_offsetInBytes(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void ShouldSetAndGetDataBytes(bool dynamic) { var vertexBuffer = (dynamic) @@ -119,6 +130,7 @@ public void ShouldSetAndGetDataBytes(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false, -1, 0, false, typeof(ArgumentOutOfRangeException))] [TestCase(false, 0, 0, false, typeof(ArgumentOutOfRangeException))] @@ -134,6 +146,7 @@ public void ShouldSetAndGetDataBytes(bool dynamic) [TestCase(false, 79, 2, false, typeof(ArgumentOutOfRangeException))] [TestCase(false, 80, 0, false, typeof(ArgumentOutOfRangeException))] [TestCase(false, 80, 1, false, typeof(ArgumentOutOfRangeException))] + [RunOnUI] public void SetDataWithElementCount(bool dynamic, int startIndex, int elementCount, bool shouldSucceed, Type expectedExceptionType) { var vertexBuffer = (dynamic) @@ -159,6 +172,7 @@ public void SetDataWithElementCount(bool dynamic, int startIndex, int elementCou vertexBuffer.Dispose(); } + [Test] [TestCase(false, 1, -1, typeof(ArgumentOutOfRangeException))] [TestCase(false, 0, 0, typeof(ArgumentOutOfRangeException))] [TestCase(false, 80, 0, null)] @@ -177,6 +191,7 @@ public void SetDataWithElementCount(bool dynamic, int startIndex, int elementCou [TestCase(false, 1, 81, typeof(ArgumentOutOfRangeException))] [TestCase(false, 2, 81, typeof(ArgumentOutOfRangeException))] #endif + [RunOnUI] public void SetDataWithElementCountAndVertexStride(bool dynamic, int elementCount, int vertexStride, Type expectedExceptionType) { var vertexBuffer = (dynamic) @@ -203,6 +218,7 @@ public void SetDataWithElementCountAndVertexStride(bool dynamic, int elementCoun } [Test] + [RunOnUI] public void BetterGetSetDataVertexStrideTest() { const int size = 5; @@ -243,6 +259,7 @@ public void BetterGetSetDataVertexStrideTest() } } + [Test] //[TestCase(true)] [TestCase(false, 1, 20, true, null)] [TestCase(false, 3, 20, true, null)] @@ -250,6 +267,7 @@ public void BetterGetSetDataVertexStrideTest() [TestCase(false, 4, 16, false, typeof(ArgumentOutOfRangeException))] [TestCase(false, 4, 20, true, null)] [TestCase(false, 5, 20, false, typeof(ArgumentOutOfRangeException))] + [RunOnUI] public void SetDataStructWithElementCountAndVertexStride(bool dynamic, int elementCount, int vertexStride, bool shouldSucceed, Type expectedExceptionType) { var vertexBuffer = (dynamic) @@ -274,8 +292,10 @@ public void SetDataStructWithElementCountAndVertexStride(bool dynamic, int eleme vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void GetPosition(bool dynamic) { var vertexBuffer = (dynamic) @@ -294,8 +314,10 @@ public void GetPosition(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void SetPosition(bool dynamic) { var vertexBuffer = (dynamic) @@ -321,8 +343,10 @@ public void SetPosition(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void GetTextureCoordinate(bool dynamic) { var vertexBuffer = (dynamic) @@ -342,8 +366,10 @@ public void GetTextureCoordinate(bool dynamic) vertexBuffer.Dispose(); } + [Test] //[TestCase(true)] [TestCase(false)] + [RunOnUI] public void SetTextureCoordinate(bool dynamic) { var vertexBuffer = (dynamic) @@ -387,6 +413,7 @@ VertexDeclaration IVertexType.VertexDeclaration } [Test] + [RunOnUI] public void ShouldSucceedWhenVertexFormatDoesMatchShader() { var vertexBuffer = new VertexBuffer( @@ -406,6 +433,7 @@ public void ShouldSucceedWhenVertexFormatDoesMatchShader() #if DESKTOPGL [Ignore("we should figure out if there's a way to check this in OpenGL")] #endif + [RunOnUI] public void ShouldThrowHelpfulExceptionWhenVertexFormatDoesNotMatchShader() { var vertexBuffer = new VertexBuffer( @@ -430,6 +458,7 @@ public void ShouldThrowHelpfulExceptionWhenVertexFormatDoesNotMatchShader() } [Test] + [RunOnUI] public void NullDeviceShouldThrowArgumentNullException() { Assert.Throws(() => diff --git a/Tests/Framework/Graphics/ViewportTest.cs b/Tests/Framework/Graphics/ViewportTest.cs index 22b0806f9a4..46ddd966f57 100644 --- a/Tests/Framework/Graphics/ViewportTest.cs +++ b/Tests/Framework/Graphics/ViewportTest.cs @@ -4,8 +4,11 @@ using NUnit.Framework; namespace MonoGame.Tests.Graphics { + [TestFixture] + [NonParallelizable] class ViewportTest : GraphicsDeviceTestFixtureBase { [Test] + [RunOnUI] public void Affects_draw_origin () { PrepareFrameCapture(); @@ -27,6 +30,7 @@ public void Affects_draw_origin () } [Test] + [RunOnUI] public void Does_not_clip_device_clear () { PrepareFrameCapture(); @@ -45,6 +49,7 @@ public void Does_not_clip_device_clear () } [Test] + [RunOnUI] public void Clips_SpriteBatch_draws () { PrepareFrameCapture(); diff --git a/Tests/Framework/Visual/MiscellaneousTests.cs b/Tests/Framework/Visual/MiscellaneousTests.cs index a2090781af6..f4b646a9f76 100644 --- a/Tests/Framework/Visual/MiscellaneousTests.cs +++ b/Tests/Framework/Visual/MiscellaneousTests.cs @@ -8,6 +8,7 @@ namespace MonoGame.Tests.Visual { [TestFixture] + [NonParallelizable] class MiscellaneousTests : VisualTestFixtureBase { [Test] @@ -21,6 +22,7 @@ class MiscellaneousTests : VisualTestFixtureBase #else [Ignore ("Microsoft.Xna.Framework.Graphics.MonoGameGLException : GL.GetError() returned 1286. Invesigate")] #endif + [RunOnUI] public void DrawOrder_falls_back_to_order_of_addition_to_Game () { Game.PreDrawWith += (sender, e) => { @@ -34,6 +36,7 @@ public void DrawOrder_falls_back_to_order_of_addition_to_Game () [TestCase(true)] [TestCase(false)] [Ignore("Fix me!")] + [RunOnUI] public void TexturedQuad_lighting (bool enableLighting) { Game.Components.Add (new TexturedQuadComponent (Game, enableLighting)); @@ -41,6 +44,7 @@ public void TexturedQuad_lighting (bool enableLighting) } [Test, Ignore("Fix me!")] + [RunOnUI] public void SpaceshipModel () { Game.Components.Add (new SpaceshipModelDrawComponent(Game)); diff --git a/Tests/MonoGame.Tests.DesktopGL.csproj b/Tests/MonoGame.Tests.DesktopGL.csproj index b3fb9d9f85c..7459107f627 100644 --- a/Tests/MonoGame.Tests.DesktopGL.csproj +++ b/Tests/MonoGame.Tests.DesktopGL.csproj @@ -8,6 +8,9 @@ false false DESKTOPGL + $(DefineConstants);MACOS + $(DefineConstants);WINDOWS + $(DefineConstants);LINUX diff --git a/Tests/Runner/Desktop/MainThreadSynchronizationContext.cs b/Tests/Runner/Desktop/MainThreadSynchronizationContext.cs new file mode 100644 index 00000000000..5f1492d0234 --- /dev/null +++ b/Tests/Runner/Desktop/MainThreadSynchronizationContext.cs @@ -0,0 +1,60 @@ +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Threading; +using NUnit.Framework; +namespace MonoGame.Tests +{ + /// + /// This class will run any test on the main UI thread. + /// This is required for SDL Graphics Tests. + /// Add the [RunOnUI] attribute to the test to get it to run on the UI thread. + /// + public class MainThreadSynchronizationContext : SynchronizationContext + { + private readonly BlockingCollection<(SendOrPostCallback, object, ManualResetEvent, TestContext)> _callbackQueue = new BlockingCollection<(SendOrPostCallback, object, ManualResetEvent, TestContext)>(); + private readonly Thread _mainThread; + + public MainThreadSynchronizationContext(Thread mainThread) + { + _mainThread = mainThread; + } + + public override void Post(SendOrPostCallback d, object state) + { + _callbackQueue.TryAdd((d, state, new ManualResetEvent(false), TestContext.CurrentContext)); + } + + public override void Send(SendOrPostCallback d, object state) + { + var ev = new ManualResetEvent(false); + _callbackQueue.TryAdd((d, state, ev, TestContext.CurrentContext)); + ev.WaitOne(); + } + + public void End() + { + _callbackQueue.CompleteAdding(); + } + + public void ExecuteQueuedCallbacks() + { + foreach (var workItem in _callbackQueue.GetConsumingEnumerable()) + { + var (callback, state, ev, context) = workItem; + Extensions.RegisterTestWtihContext(TestContext.CurrentContext, context.Test); + try + { + callback(state); + } + finally + { + Extensions.UnRegisterTestWtihContext(TestContext.CurrentContext); + } + if (ev != null) + { + ev.Set(); + } + } + } + } +} \ No newline at end of file diff --git a/Tests/Runner/Desktop/RunOnUIAttribute.cs b/Tests/Runner/Desktop/RunOnUIAttribute.cs new file mode 100644 index 00000000000..47aac42ba2b --- /dev/null +++ b/Tests/Runner/Desktop/RunOnUIAttribute.cs @@ -0,0 +1,33 @@ +using System; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Commands; + +namespace MonoGame.Tests +{ + /// + /// Marshall the test onto the main UI thread. + /// + [System.AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] + sealed class RunOnUIAttribute : Attribute, IWrapSetUpTearDown, IWrapTestMethod + { +//#if !DESKTOPGL +// public TestCommand Wrap(TestCommand command) => command; +//#else + public TestCommand Wrap(TestCommand command) => new RunOnUICommand(command); + + class RunOnUICommand : DelegatingTestCommand + { + public RunOnUICommand(TestCommand innerCommand) + : base(innerCommand) + { + } + + public override TestResult Execute(TestExecutionContext context) + { + return Program.Invoke(() => innerCommand.Execute(context), context.CurrentTest.MakeTestResult ()); + } + } +//#endif + } +} \ No newline at end of file diff --git a/Tests/Runner/Extensions.cs b/Tests/Runner/Extensions.cs index c79dde382dd..f87105b877b 100644 --- a/Tests/Runner/Extensions.cs +++ b/Tests/Runner/Extensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -10,6 +11,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using NUnit.Framework; +using NUnit.Framework.Internal; namespace MonoGame.Tests { static class Extensions { @@ -63,6 +65,18 @@ public static StackFrame FindTestEntryFrame (this StackTrace self) return null; } + static ConcurrentDictionary tests = new ConcurrentDictionary(); + + public static void RegisterTestWtihContext (TestContext context, TestContext.TestAdapter test) + { + tests.TryAdd(context.Test.ID, test); + } + + public static void UnRegisterTestWtihContext (TestContext context) + { + tests.Clear (); + } + public static StackFrame GetTestEntryStackFrame (this StackTrace self) { var stackFrame = self.FindTestEntryFrame (); @@ -77,9 +91,12 @@ public static string GetTestFolderName (this TestContext self) // TODO: Add support for a custom attribute to override // the calculated name. //var method = self.GetMethod (); + if (!tests.TryGetValue (self.Test.ID, out TestContext.TestAdapter test)) { + test = self.Test; + } - var fullTypeName = self.Test.FullName.Remove ( - self.Test.FullName.Length - (self.Test.Name.Length + 1)); + var fullTypeName = test.FullName.Remove ( + test.FullName.Length - (test.Name.Length + 1)); var tokens = fullTypeName.Split('.'); var typeName = tokens [tokens.Length - 1]; @@ -95,15 +112,18 @@ public static string GetTestFrameFileNameFormat (this TestContext self, int maxF { // TODO: Add support for a custom attribute to override // the calculated name. + if (!tests.TryGetValue (self.Test.ID, out TestContext.TestAdapter test)) { + test = self.Test; + } if (maxFrameNumber == 0) - return self.Test.Name.ReplaceInvalidFileNameChars() + "-{0}.png"; + return test.Name.ReplaceInvalidFileNameChars() + "-{0}.png"; if (maxFrameNumber == 1) - return self.Test.Name.ReplaceInvalidFileNameChars() + ".png"; + return test.Name.ReplaceInvalidFileNameChars() + ".png"; int numDigits = 1 + (int)Math.Log10 (maxFrameNumber + 1); - var builder = new StringBuilder (self.Test.Name.ReplaceInvalidFileNameChars ()); + var builder = new StringBuilder (test.Name.ReplaceInvalidFileNameChars ()); builder.Append ("-{0:"); builder.Append ('0', numDigits); builder.Append ("}.png"); diff --git a/Tests/Runner/Program.cs b/Tests/Runner/Program.cs index 533bb31d9fd..36c7a6c5e60 100644 --- a/Tests/Runner/Program.cs +++ b/Tests/Runner/Program.cs @@ -6,14 +6,57 @@ using System.IO; using NUnitLite; using NUnit.Framework; +using NUnit.Common; +using NUnit.Framework.Api; +using NUnit.Framework.Interfaces; +using System.Reflection; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Filters; +using System.Collections.Generic; +using NUnit; +using System.Diagnostics; +using NUnit.Framework.Internal.Execution; +using NUnit.Framework.Internal.Commands; +using System.Threading; +using Microsoft.VisualBasic; +using System.Collections.Concurrent; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Serialization; namespace MonoGame.Tests { static class Program { - static int Main(string [] args) + static Thread mainThread = Thread.CurrentThread; + static MainThreadSynchronizationContext mainThreadSynchronizationContext; + public static TestResult Invoke (Func func, TestResult result) { - return new AutoRun().Execute(args); + if (Thread.CurrentThread != mainThread) { + TestResult r = result; + mainThreadSynchronizationContext.Send (state => { + try { + r = func(); + } catch (Exception ex) { + r.RecordException (ex); + } + }, null); + return r; + } else { + return func(); + } + } + static async Task Main(string [] args) + { + mainThread = Thread.CurrentThread; + mainThreadSynchronizationContext = new MainThreadSynchronizationContext(mainThread); + SynchronizationContext.SetSynchronizationContext (mainThreadSynchronizationContext); + int result = 0; + var task = Task.Run (() => result = new AutoRun().Execute(args)).ContinueWith ((t) => { + mainThreadSynchronizationContext.End (); + }, continuationOptions: TaskContinuationOptions.ExecuteSynchronously); + mainThreadSynchronizationContext.ExecuteQueuedCallbacks (); + await task; + return result; } } } diff --git a/Tools/MonoGame.Tools.Tests/AudioContentTests.cs b/Tools/MonoGame.Tools.Tests/AudioContentTests.cs index a43b279ca43..089eaf3ea46 100644 --- a/Tools/MonoGame.Tools.Tests/AudioContentTests.cs +++ b/Tools/MonoGame.Tools.Tests/AudioContentTests.cs @@ -11,9 +11,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS && CI - [Ignore("Hanging on Mac in CI?")] -#endif + [Category("Audio")] class AudioContentTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs b/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs index bd4e4357caa..4f7a57841be 100644 --- a/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs +++ b/Tools/MonoGame.Tools.Tests/EffectProcessorTests.cs @@ -10,9 +10,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS || LINUX - [Ignore("Does not work on CI yet. need to get wine working.")] -#endif + [Category("Effects")] class EffectProcessorTests { class ImporterContext : ContentImporterContext diff --git a/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj b/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj index d36daf88307..7e9694c3799 100644 --- a/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj +++ b/Tools/MonoGame.Tools.Tests/MonoGame.Tools.Tests.csproj @@ -1087,4 +1087,14 @@ Assets\Effects\Stock\Structures.fxh + + + MonoGame.Content.Builder.Task.targets + PreserveNewest + + + MonoGame.Content.Builder.Task.props + PreserveNewest + + diff --git a/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs b/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs index 665988bf001..7e0b7d8331f 100644 --- a/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/Mp3ImporterTests.cs @@ -9,9 +9,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS && CI - [Ignore("Hanging on Mac in CI?")] -#endif + [Category("Audio")] class Mp3ImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/OggImporterTests.cs b/Tools/MonoGame.Tools.Tests/OggImporterTests.cs index eeecedf9b74..d48b5c999cd 100644 --- a/Tools/MonoGame.Tools.Tests/OggImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/OggImporterTests.cs @@ -9,9 +9,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS && CI - [Ignore("Hanging on Mac in CI?")] -#endif + [Category("Audio")] class OggImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs b/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs index c7e20d5e0da..2c29a8dd635 100644 --- a/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/TextureImporterTests.cs @@ -106,7 +106,7 @@ public void ImportTif( ) /// [Test] #if MACOS || LINUX - [Ignore("Does not work on Unix based systems. We need to get wine working on CI.")] + [Ignore("Does not work on Unix based systems. Its odd the test passes?")] #endif public void ImportImageWithBadContent( ) { diff --git a/Tools/MonoGame.Tools.Tests/TextureProcessorTests.cs b/Tools/MonoGame.Tools.Tests/TextureProcessorTests.cs index ceb0e6688bb..2f47bf7dc54 100644 --- a/Tools/MonoGame.Tools.Tests/TextureProcessorTests.cs +++ b/Tools/MonoGame.Tools.Tests/TextureProcessorTests.cs @@ -11,6 +11,7 @@ namespace MonoGame.Tests.ContentPipeline { + [TestFixture] class TextureProcessorTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/WavImporterTests.cs b/Tools/MonoGame.Tools.Tests/WavImporterTests.cs index 0439e40a0ad..04e7c8b45ea 100644 --- a/Tools/MonoGame.Tools.Tests/WavImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/WavImporterTests.cs @@ -9,9 +9,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS && CI - [Ignore("Hanging on Mac in CI")] -#endif + [Category("Audio")] class WavImporterTests { [Test] diff --git a/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs b/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs index 7bca033404f..af28b8ae358 100644 --- a/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs +++ b/Tools/MonoGame.Tools.Tests/WmaImporterTests.cs @@ -9,9 +9,7 @@ namespace MonoGame.Tests.ContentPipeline { -#if MACOS && CI - [Ignore("Hanging on Mac in CI?")] -#endif + [Category("Audio")] class WmaImporterTests { [Test] diff --git a/build/BuildContext.cs b/build/BuildContext.cs index e23ad2c4445..d67cc834b52 100644 --- a/build/BuildContext.cs +++ b/build/BuildContext.cs @@ -9,6 +9,7 @@ public enum ProjectType Framework, Tools, Templates, + Tests, ContentPipeline, MGCBEditor, MGCBEditorLauncher @@ -24,7 +25,7 @@ public BuildContext(ICakeContext context) : base(context) { var repositoryUrl = context.Argument("build-repository", DefaultRepositoryUrl); var buildConfiguration = context.Argument("build-configuration", "Release"); - BuildOutput = context.Argument("build-output", "artifacts"); + BuildOutput = context.Argument("build-output", "Artifacts"); NuGetsDirectory = $"{BuildOutput}/NuGet/"; var tags = GitAliases.GitTags(context, "."); @@ -150,6 +151,7 @@ public BuildContext(ICakeContext context) : base(context) ProjectType.Framework => $"MonoGame.Framework/MonoGame.Framework.{id}.csproj", ProjectType.Tools => $"Tools/{id}/{id}.csproj", ProjectType.Templates => $"Templates/{id}/{id}.csproj", + ProjectType.Tests => $"Tests/{id}.csproj", ProjectType.ContentPipeline => "MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj", ProjectType.MGCBEditor => $"Tools/MonoGame.Content.Builder.Editor/MonoGame.Content.Builder.Editor.{id}.csproj", ProjectType.MGCBEditorLauncher => $"Tools/MonoGame.Content.Builder.Editor.Launcher/MonoGame.Content.Builder.Editor.Launcher.{id}.csproj", diff --git a/build/BuildTestsTasks/BuildTestsTask.cs b/build/BuildTestsTasks/BuildTestsTask.cs new file mode 100644 index 00000000000..67c5aea9b2d --- /dev/null +++ b/build/BuildTestsTasks/BuildTestsTask.cs @@ -0,0 +1,15 @@ + +namespace BuildScripts; + +[TaskName("Build Tests")] +[IsDependentOn(typeof(BuildFrameworksTask))] +[IsDependentOn(typeof(BuildContentPipelineTask))] +public sealed class BuildTestsTask : FrostingTask +{ + public override void Run(BuildContext context) + { + context.DotNetBuild(context.GetProjectPath(ProjectType.Tests, "MonoGame.Tests.DesktopGL"), context.DotNetBuildSettings); + if (context.IsRunningOnWindows()) + context.DotNetBuild(context.GetProjectPath(ProjectType.Tests, "MonoGame.Tests.WindowsDX"), context.DotNetBuildSettings); + } +} \ No newline at end of file diff --git a/build/BuildToolsTasks/BuildToolTestsTask.cs b/build/BuildToolsTasks/BuildToolTestsTask.cs index 15f9c9f23e5..1d0f43c6a67 100644 --- a/build/BuildToolsTasks/BuildToolTestsTask.cs +++ b/build/BuildToolsTasks/BuildToolTestsTask.cs @@ -1,7 +1,7 @@ namespace BuildScripts; -[TaskName("Build ToolTests")] +[TaskName("Build Tool Tests")] [IsDependentOn(typeof(BuildContentPipelineTask))] public sealed class BuildToolTestsTask : FrostingTask { diff --git a/build/DeployTasks/UploadArtifactsTask.cs b/build/DeployTasks/UploadArtifactsTask.cs index c73ddc206a5..61abf7eceef 100644 --- a/build/DeployTasks/UploadArtifactsTask.cs +++ b/build/DeployTasks/UploadArtifactsTask.cs @@ -11,10 +11,14 @@ public override async Task RunAsync(BuildContext context) var os = context.Environment.Platform.Family switch { PlatformFamily.Windows => "windows", - PlatformFamily.OSX => "mac", + PlatformFamily.OSX => "macos", _ => "linux" }; await context.GitHubActions().Commands.UploadArtifact(new DirectoryPath(context.NuGetsDirectory.FullPath), $"nuget-{os}"); + await context.GitHubActions().Commands.UploadArtifact(new DirectoryPath(System.IO.Path.Combine(context.BuildOutput, "Tests", "Tools", "Release")), $"tests-tools-{os}"); + await context.GitHubActions().Commands.UploadArtifact(new DirectoryPath(System.IO.Path.Combine(context.BuildOutput, "Tests", "DesktopGL", "Release")), $"tests-desktopgl-{os}"); + if (context.IsRunningOnWindows()) + await context.GitHubActions().Commands.UploadArtifact(new DirectoryPath(System.IO.Path.Combine(context.BuildOutput, "Tests", "WindowsDX", "Release")), $"tests-windowsdx-{os}"); } } diff --git a/build/Tasks.cs b/build/Tasks.cs index 214275926c4..7fc3f294fbe 100644 --- a/build/Tasks.cs +++ b/build/Tasks.cs @@ -23,16 +23,17 @@ public sealed class BuildToolsTask : FrostingTask { } [IsDependentOn(typeof(BuildVSTemplatesTask))] public sealed class BuildTemplatesTask : FrostingTask { } -[TaskName("Build Tests")] +[TaskName("Build All Tests")] +[IsDependentOn(typeof(BuildTestsTask))] [IsDependentOn(typeof(BuildToolTestsTask))] -public sealed class BuildTestsTask : FrostingTask { } +public sealed class BuildAllTestsTask : FrostingTask { } [TaskName("Build All")] [IsDependentOn(typeof(BuildFrameworksTask))] [IsDependentOn(typeof(BuildToolsTask))] [IsDependentOn(typeof(BuildTemplatesTask))] -[IsDependentOn(typeof(BuildTestsTask))] +[IsDependentOn(typeof(BuildAllTestsTask))] public sealed class BuildAllTask : FrostingTask { } [TaskName("Deploy")] @@ -40,6 +41,10 @@ public sealed class BuildAllTask : FrostingTask { } [IsDependentOn(typeof(DeployNuGetsToNuGetOrgTask))] public sealed class DeployTask : FrostingTask { } +[TaskName("Test")] +[IsDependentOn(typeof(DownloadTestArtifactsTask))] +public sealed class TestTask : FrostingTask {} + [TaskName("Default")] [IsDependentOn(typeof(BuildAllTask))] public sealed class DefaultTask : FrostingTask { } diff --git a/build/TestTasks/DownloadTestArtifactsTask.cs b/build/TestTasks/DownloadTestArtifactsTask.cs new file mode 100644 index 00000000000..7356fe8b428 --- /dev/null +++ b/build/TestTasks/DownloadTestArtifactsTask.cs @@ -0,0 +1,23 @@ + +namespace BuildScripts; + +[TaskName("DownloadTestArtifacts")] +public sealed class DownloadTestArtifactsTask : AsyncFrostingTask +{ + public override bool ShouldRun(BuildContext context) => context.BuildSystem().IsRunningOnGitHubActions; + + public override async Task RunAsync(BuildContext context) + { + var os = context.Environment.Platform.Family switch + { + PlatformFamily.Windows => "windows", + PlatformFamily.OSX => "macos", + _ => "linux" + }; + context.CreateDirectory("tests-tools"); + await context.GitHubActions().Commands.DownloadArtifact($"tests-tools-{os}", "tests-tools"); + await context.GitHubActions().Commands.DownloadArtifact($"tests-desktopgl-{os}", "tests-desktopgl"); + if (context.IsRunningOnWindows()) + await context.GitHubActions().Commands.DownloadArtifact($"tests-windowsdx-{os}", "tests-windowsdx"); + } +} From b9dddadda2139a5971d24aad15446f657c856ccf Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 24 Sep 2024 09:32:27 +0100 Subject: [PATCH 6/6] Fix Deploy Task Error (#8502) The commit 2dd7b76b changed the name of the Nuget packages we archive. The DownloadArtifactsTask was not updated to match. It should have been using `macos` rather than `mac` for it nuget package name. --- build/DeployTasks/DownloadArtifactsTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/DeployTasks/DownloadArtifactsTask.cs b/build/DeployTasks/DownloadArtifactsTask.cs index 9a08ecd052a..ff014c846a1 100644 --- a/build/DeployTasks/DownloadArtifactsTask.cs +++ b/build/DeployTasks/DownloadArtifactsTask.cs @@ -9,7 +9,7 @@ public sealed class DownloadArtifactsTask : AsyncFrostingTask public override async Task RunAsync(BuildContext context) { context.CreateDirectory("nugets"); - foreach (var os in new[] { "windows", "mac", "linux" }) + foreach (var os in new[] { "windows", "macos", "linux" }) await context.GitHubActions().Commands.DownloadArtifact($"nuget-{os}", "nugets"); } }