Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Support for RenderTargetBitmap, BitmapEncoder, SoftwareBitmap #7830

8 changes: 8 additions & 0 deletions build/PackageDiffIgnore.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8856,6 +8856,14 @@
<Member
fullName="System.Void Windows.UI.UIContext..ctor()"
reason="Not part of UWP API" />
<!-- BEGIN BitmapEncoder -->
<Member
fullName="System.Void Windows.Graphics.Imaging.BitmapEncoder..ctor()"
reason="Add private ctor for initialize BitmapEncoder" />
<Member
fullName="System.Void Windows.Graphics.Imaging.BitmapEncoder::.ctor()"
reason="Add private ctor for initialize BitmapEncoder" />
<!-- END BitmapEncoder API -->
</Methods>
<Properties>
</Properties>
Expand Down
114 changes: 114 additions & 0 deletions build/ci/.azure-devops-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,117 @@ jobs:
PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uno-macos-artifacts
ArtifactType: Container

- job: macOS_Runtime_Tests
timeoutInMinutes: 90
condition: eq(1,2)
displayName: macOS SamplesApp Runtime Tests

variables:
CI_Build: true
SourceLinkEnabled: false
NUGET_PACKAGES: $(build.sourcesdirectory)/.nuget

dependsOn: macOS

pool:
vmImage: ${{ parameters.vmImage }}

steps:
- checkout: none
clean: true

- template: templates/dotnet-install.yml
- template: templates/optimize-roslyn-mono.yml

- template: templates/nuget-cache.yml
parameters:
nugetPackages: $(NUGET_PACKAGES)

- task: DownloadBuildArtifacts@0
inputs:
artifactName: uno-macos-artifacts
downloadPath: '$(build.sourcesdirectory)/build'

- task: PowerShell@2
displayName: 'Install coreutils'
inputs:
targetType: inline
script: |
brew install coreutils

- script: |
cd $(build.sourcesdirectory)/build/uno-macos-artifacts
installer -pkg SamplesApp.macOS-1.0.pkg -target CurrentUserHomeDirectory

displayName: Install SamplesApp

- script: |
timeout 70m /Applications/SamplesApp.macOS.app/Contents/MacOS/SamplesApp.macOS --runtime-tests=$(build.sourcesdirectory)/build/macOS-runtime-tests-results.xml

displayName: Run macOS Runtime Tests

- task: PublishTestResults@2
displayName: Publish macOS Runtime Tests
condition: always()
inputs:
testRunTitle: 'macOS Runtime Tests'
testResultsFormat: 'NUnit'
testResultsFiles: '$(build.sourcesdirectory)/build/macOS-runtime-tests-results.xml'
failTaskOnFailedTests: true

- job: macOS_Screenshot_Tests
timeoutInMinutes: 100
displayName: macOS SamplesApp Screenshot Test

variables:
CI_Build: true
SourceLinkEnabled: false
NUGET_PACKAGES: $(build.sourcesdirectory)/.nuget

dependsOn: macOS

pool:
vmImage: ${{ parameters.vmImage }}

steps:
- checkout: none
clean: true

- template: templates/dotnet-install.yml
- template: templates/optimize-roslyn-mono.yml

- template: templates/nuget-cache.yml
parameters:
nugetPackages: $(NUGET_PACKAGES)

- task: DownloadBuildArtifacts@0
inputs:
artifactName: uno-macos-artifacts
downloadPath: '$(build.sourcesdirectory)/build'

- task: PowerShell@2
displayName: 'Install coreutils'
inputs:
targetType: inline
script: |
brew install coreutils

- script: |
cd $(build.sourcesdirectory)/build/uno-macos-artifacts
installer -pkg SamplesApp.macOS-1.0.pkg -target CurrentUserHomeDirectory
jeromelaban marked this conversation as resolved.
Show resolved Hide resolved

displayName: Install SamplesApp

- script: |
timeout 90m /Applications/SamplesApp.macOS.app/Contents/MacOS/SamplesApp.macOS --auto-screenshots=$(build.artifactstagingdirectory)/screenshots/macOS-screenshots

displayName: Run macOS UI Snapshot Tests

- task: PublishBuildArtifacts@1
displayName: Publish macOS Screenshots
condition: always()
inputs:
PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uitests-results
ArtifactType: Container
1 change: 1 addition & 0 deletions build/ci/.azure-devops-screenshot-compare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
- iOS_Snapshot_Tests_Group_02
- iOS_Snapshot_Tests_Group_03
- iOS_Snapshot_Tests_Group_04
- macOS_Screenshot_Tests

condition: or(succeeded(), and(failed(), ge(variables['System.StageAttempt'], 5)))

Expand Down
10 changes: 7 additions & 3 deletions src/SamplesApp/SamplesApp.Droid/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Runtime.InteropServices;
using Android.App;

// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UnoQuickStart.Droid")]
Expand All @@ -19,11 +19,11 @@
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
Expand All @@ -36,3 +36,7 @@
[assembly: UsesPermission("android.permission.ACCESS_NETWORK_STATE")]
[assembly: UsesPermission("android.permission.SET_WALLPAPER")]
[assembly: UsesPermission("android.permission.READ_CONTACTS")]
[assembly: UsesPermission("android.permission.MANAGE_DOCUMENTS")]
[assembly: UsesPermission("android.permission.MANAGE_EXTERNAL_STORAGE")]
[assembly: UsesPermission("android.permission.MANAGE_MEDIA")]
[assembly: UsesPermission("android.permission.USE_FULL_SCREEN_INTENT")]
9 changes: 5 additions & 4 deletions src/SamplesApp/SamplesApp.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,14 @@ override void OnLaunched(LaunchActivatedEventArgs e)

private static async Task<bool> HandleSkiaAutoScreenshots(LaunchActivatedEventArgs e)
{
#if __SKIA__
#if __SKIA__ || __MACOS__
var runAutoScreenshotsParam =
e.Arguments.Split(';').FirstOrDefault(a => a.StartsWith("--auto-screenshots"));

var screenshotsPath = runAutoScreenshotsParam?.Split('=').LastOrDefault();

if (!string.IsNullOrEmpty(screenshotsPath))
{
var sw = Stopwatch.StartNew();
var n = Windows.UI.Xaml.Window.Current.Dispatcher.RunIdleAsync(
_ =>
{
Expand All @@ -170,7 +169,7 @@ private static async Task<bool> HandleSkiaAutoScreenshots(LaunchActivatedEventAr

private static async Task<bool> HandleSkiaRuntimeTests(LaunchActivatedEventArgs e)
{
#if __SKIA__
#if __SKIA__ || __MACOS__
var runRuntimeTestsResultsParam =
e.Arguments.Split(';').FirstOrDefault(a => a.StartsWith("--runtime-tests"));

Expand All @@ -180,7 +179,7 @@ private static async Task<bool> HandleSkiaRuntimeTests(LaunchActivatedEventArgs
{
Console.WriteLine($"HandleSkiaRuntimeTests: {runtimeTestResultFilePath}");

_ = Window.Current.Dispatcher.RunIdleAsync(async _ =>
var runner = new Action(async () =>
{
// let the app finish its startup
await Task.Delay(TimeSpan.FromSeconds(5));
Expand All @@ -196,6 +195,8 @@ await SampleControl.Presentation.SampleChooserViewModel.Instance.RunRuntimeTests
);
});

await Task.Run(runner);

return true;
}
#endif
Expand Down
2 changes: 0 additions & 2 deletions src/SamplesApp/SamplesApp.Skia.Gtk/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ public static void Main(string[] args)

var host = new GtkHost(() => new SamplesApp.App());

SampleControl.Presentation.SampleChooserViewModel.TakeScreenShot = filePath => host.TakeScreenshot(filePath);

host.Run();
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/SamplesApp/SamplesApp.UITests/SamplesApp.UITests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

<ItemGroup>
<Folder Include="MessageDialogTests\" />
<Folder Include="Windows_UI_Xaml_Media_Imaging\RenderTargetBitmap_Tests_ExpectedResults\" />
<Folder Include="Windows_UI_Xaml_Shapes\Basics_Shapes_Tests_EpectedResults\" />
</ItemGroup>

Expand All @@ -49,6 +50,9 @@
<Compile Include="$(MSBuildThisFileDirectory)..\..\Uno.UWP\Devices\Input\PointerDeviceType.cs">
<Link>TestFramework\PointerDeviceType.cs</Link>
</Compile>
<None Update="Windows_UI_Xaml_Media_Imaging\RenderTargetBitmap_Tests_ExpectedResults\Border.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.IO;
using NUnit.Framework;
using SamplesApp.UITests.Extensions;
using SamplesApp.UITests.TestFramework;
using Uno.UITest.Helpers.Queries;

namespace SamplesApp.UITests.Windows_UI_Xaml_Media_Imaging
{
[TestFixture]
[ActivePlatforms(Platform.iOS | Platform.Android)]
public partial class RenderTargetBitmap_Tests : SampleControlUITestBase
{
private const int TestTimeout = 7 * 60 * 1000;
[Test]
[AutoRetry]
[Timeout(TestTimeout)]
public void When_Render_Border()
=> Validate("Border");

public void Validate(string controlName, PixelTolerance? tolerance = null)
{
Run("UITests.Windows_UI_Xaml_Media_Imaging.RenderTargetBitmaps", skipInitialScreenshot: true);

var ctrl = new QueryEx(q => q.Marked("_renderTargetTestRoot"));

var expectedDirectory = Path.Combine(
TestContext.CurrentContext.TestDirectory,
nameof(Windows_UI_Xaml_Media_Imaging) + "/RenderTargetBitmap_Tests_ExpectedResults");
var actualDirectory = Path.Combine(
TestContext.CurrentContext.WorkDirectory,
nameof(Windows_UI_Xaml_Media_Imaging),
nameof(RenderTargetBitmap_Tests),
controlName);

tolerance = tolerance ?? (new PixelTolerance()
.WithColor(132) // We are almost only trying to detect edges
.WithOffset(3, 3, LocationToleranceKind.PerPixel)
.Discrete(2));

ctrl.SetDependencyPropertyValue("RunTest", controlName);
_app.WaitFor(() => !string.IsNullOrWhiteSpace(ctrl.GetDependencyPropertyValue<string>("TestResult"))
, timeout: TimeSpan.FromMinutes(1));

var testResultsRaw = ctrl.GetDependencyPropertyValue<string>("TestResult");

var testResults = testResultsRaw.Split(';');
Assert.That(testResults.Length, Is.EqualTo(2));

var isSuccess = testResults[0] == "SUCCESS";
var data = Convert.FromBase64String(testResults[1]);

Assert.IsNotEmpty(data, "Invalid data");

var target = Path
.Combine(actualDirectory, controlName + (isSuccess ? ".png" : ".txt"))
.GetNormalizedLongPath();
var targetFile = new FileInfo(target);

targetFile.Directory.Create();
File.WriteAllBytes(target, data);
SetOptions(targetFile, new ScreenshotOptions { IgnoreInSnapshotCompare = true });
TestContext.AddTestAttachment(target, controlName);

if (!isSuccess)
{
Assert.Fail($"No test result for {controlName}.");
}

var expected = new FileInfo(Path.Combine(expectedDirectory, $"{controlName}.png"));
if (!expected.Exists)
{
Assert.Fail($"Expected screenshot does not exists ({expected.FullName})");
}

var scale = _app.GetDisplayScreenScaling();
ImageAssert.AreEqual(expected, ImageAssert.FirstQuadrant,
targetFile, ImageAssert.FirstQuadrant,
scale, tolerance.Value);
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ public void ValidateShape(string shapeName, PixelTolerance? tolerance = null)
}

using (var actual = (Bitmap)testResult)
{
var scale = _app.GetDisplayScreenScaling();
{
var scale = 1d;
MartinZikmund marked this conversation as resolved.
Show resolved Hide resolved
ImageAssert.AreAlmostEqual(expected, ImageAssert.FirstQuadrant, actual, ImageAssert.FirstQuadrant, scale, tolerance.Value);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
#pragma warning disable 105 // Disabled until the tree is migrate to WinUI

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using SampleControl.Entities;
using Uno.UI.Samples.Controls;
using Uno.UI.Samples.Entities;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Globalization;
using Windows.UI.Xaml.Data;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.Storage;
using Uno.Extensions;
using Microsoft.Extensions.Logging;
using Windows.UI.Xaml;
using System.IO;
using Uno.Disposables;
using System.ComponentModel;
using Uno.UI.Common;
using Microsoft.UI.Xaml.Controls;

Expand Down
Loading