浏览代码

Merge branch 'master' into system-fonts

Nikita Tsukanov 6 年之前
父节点
当前提交
8da975d13e
共有 30 个文件被更改,包括 190 次插入86 次删除
  1. 29 8
      Avalonia.sln
  2. 7 0
      azure-pipelines.yml
  3. 5 0
      build/NetFX.props
  4. 8 0
      build/UnitTests.NetFX.props
  5. 1 0
      build/xunit.runner.mono.json
  6. 1 1
      global.json
  7. 39 19
      nukebuild/Build.cs
  8. 1 0
      src/Avalonia.Animation/AnimatorKeyFrame.cs
  9. 1 1
      src/Avalonia.Animation/IterationCount.cs
  10. 2 2
      src/Avalonia.Base/Collections/AvaloniaDictionary.cs
  11. 1 1
      src/Avalonia.Base/Collections/AvaloniaList.cs
  12. 1 0
      src/Avalonia.Base/Platform/IAssetLoader.cs
  13. 1 1
      src/Avalonia.Controls/Calendar/DatePicker.cs
  14. 2 2
      src/Avalonia.Controls/GridLength.cs
  15. 1 1
      src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
  16. 1 1
      src/Avalonia.Styling/Styling/Setter.cs
  17. 1 0
      src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
  18. 1 0
      src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
  19. 4 2
      tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj
  20. 3 1
      tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
  21. 6 1
      tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs
  22. 13 11
      tests/Avalonia.Base.UnitTests/Data/Core/Plugins/DataAnnotationsValidationPluginTests.cs
  23. 4 2
      tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
  24. 32 21
      tests/Avalonia.Controls.UnitTests/GridLayoutTests.cs
  25. 4 2
      tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj
  26. 4 1
      tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj
  27. 4 2
      tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj
  28. 4 2
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  29. 4 2
      tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
  30. 5 2
      tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj

+ 29 - 8
Avalonia.sln

@@ -1,4 +1,5 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.27130.2027
 MinimumVisualStudioVersion = 10.0.40219.1
@@ -130,6 +131,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 	ProjectSection(SolutionItems) = preProject
 		build\Base.props = build\Base.props
 		build\Binding.props = build\Binding.props
+		build\BuildTargets.targets = build\BuildTargets.targets
 		build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
 		build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
 		build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props
@@ -147,7 +149,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 		build\Splat.props = build\Splat.props
 		build\System.Memory.props = build\System.Memory.props
 		build\XUnit.props = build\XUnit.props
-		build\BuildTargets.targets = build\BuildTargets.targets
 	EndProjectSection
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
@@ -189,11 +190,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia", "packages\Avalon
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{3C471044-3640-45E3-B1B2-16D2FF8399EE}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build.csproj", "{3F00BC43-5095-477F-93D8-E65B08179A00}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}"
 EndProject
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
@@ -220,10 +221,6 @@ Global
 		Release|iPhoneSimulator = Release|iPhoneSimulator
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU
 		{B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
 		{B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
 		{B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@@ -1722,6 +1719,30 @@ Global
 		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhone.Build.0 = Release|Any CPU
 		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
 		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
 		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU

+ 7 - 0
azure-pipelines.yml

@@ -38,6 +38,13 @@ jobs:
     inputs:
       version: '2.1.403'
 
+  - task: CmdLine@2
+    displayName: 'Install Mono 5.18'
+    inputs:
+      script: |
+        curl -o ./mono.pkg https://download.mono-project.com/archive/5.18.0/macos-10-universal/MonoFramework-MDK-5.18.0.225.macos10.xamarin.universal.pkg 
+        sudo installer -verbose -pkg ./mono.pkg -target /
+
   - task: Xcode@5
     inputs:
       actions: 'build'

+ 5 - 0
build/NetFX.props

@@ -3,4 +3,9 @@
     <FrameworkPathOverride>/usr/lib/mono/4.6.1-api</FrameworkPathOverride>
     <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api</FrameworkPathOverride>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(TargetFramework)' == 'net47' and '$(OS)' == 'Unix' ">
+    <FrameworkPathOverride>/usr/lib/mono/4.7-api/</FrameworkPathOverride>
+    <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api</FrameworkPathOverride>
+  </PropertyGroup>
+
 </Project>

+ 8 - 0
build/UnitTests.NetFX.props

@@ -0,0 +1,8 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildThisFileDirectory)/NetFX.props" />	
+  <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
+    <Content Include="$(MSBuildThisFileDirectory)/xunit.runner.mono.json" Link="xunit.runner.json" >
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 1 - 0
build/xunit.runner.mono.json

@@ -0,0 +1 @@
+{ "appDomain": "denied" }

+ 1 - 1
global.json

@@ -1,7 +1,7 @@
 {
     "msbuild-sdks": {
         "Microsoft.Build.Traversal": "1.0.43",
-        "MSBuild.Sdk.Extras": "1.6.46",
+        "MSBuild.Sdk.Extras": "1.6.65",
         "AggregatePackage.NuGet.Sdk" : "0.1.12"
     }
 }

+ 39 - 19
nukebuild/Build.cs

@@ -5,6 +5,7 @@ using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
 using System.Threading;
+using System.Xml.Linq;
 using Nuke.Common;
 using Nuke.Common.Git;
 using Nuke.Common.ProjectModel;
@@ -56,6 +57,17 @@ partial class Build : NukeBuild
         Information("IsReleasable: " + Parameters.IsReleasable);
         Information("IsMyGetRelease: " + Parameters.IsMyGetRelease);
         Information("IsNuGetRelease: " + Parameters.IsNuGetRelease);
+
+        void ExecWait(string preamble, string command, string args)
+        {
+            Console.WriteLine(preamble);
+            Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit();
+        }
+        ExecWait("dotnet version:", "dotnet", "--version");
+        if (Parameters.IsRunningOnUnix)
+            ExecWait("Mono version:", "mono", "--version");
+
+
     }
 
     Target Clean => _ => _.Executes(() =>
@@ -92,16 +104,24 @@ partial class Build : NukeBuild
                 );
         });
     
-    void RunCoreTest(string project, bool coreOnly = false)
+    void RunCoreTest(string project)
     {
         if(!project.EndsWith(".csproj"))
             project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
         Information("Running tests from " + project);
-        var frameworks = new List<string>(){"netcoreapp2.0"};
+        XDocument xdoc;
+        using (var s = File.OpenRead(project))
+            xdoc = XDocument.Load(s);
+
+        List<string> frameworks = null;
+        var targets = xdoc.Root.Descendants("TargetFrameworks").FirstOrDefault();
+        if (targets != null)
+            frameworks = targets.Value.Split(';').Where(f => !string.IsNullOrWhiteSpace(f)).ToList();
+        else 
+            frameworks = new List<string> {xdoc.Root.Descendants("TargetFramework").First().Value};
+        
         foreach(var fw in frameworks)
         {
-            if(!fw.StartsWith("netcoreapp") && coreOnly)
-                continue;
             Information("Running for " + fw);
             DotNetTest(c =>
             {
@@ -124,18 +144,18 @@ partial class Build : NukeBuild
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.Animation.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Base.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Controls.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Input.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Layout.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Markup.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Styling.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Visuals.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.Skia.UnitTests", false);
-            RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", false);
+            RunCoreTest("./tests/Avalonia.Animation.UnitTests");
+            RunCoreTest("./tests/Avalonia.Base.UnitTests");
+            RunCoreTest("./tests/Avalonia.Controls.UnitTests");
+            RunCoreTest("./tests/Avalonia.Input.UnitTests");
+            RunCoreTest("./tests/Avalonia.Interactivity.UnitTests");
+            RunCoreTest("./tests/Avalonia.Layout.UnitTests");
+            RunCoreTest("./tests/Avalonia.Markup.UnitTests");
+            RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests");
+            RunCoreTest("./tests/Avalonia.Styling.UnitTests");
+            RunCoreTest("./tests/Avalonia.Visuals.UnitTests");
+            RunCoreTest("./tests/Avalonia.Skia.UnitTests");
+            RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests");
         });
 
     Target RunRenderTests => _ => _
@@ -143,9 +163,9 @@ partial class Build : NukeBuild
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", true);
+            RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj");
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-                RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", true);
+                RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj");
         });
     
     Target RunDesignerTests => _ => _
@@ -153,7 +173,7 @@ partial class Build : NukeBuild
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", false);
+            RunCoreTest("./tests/Avalonia.DesignerSupport.Tests");
         });
 
     [PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit;

+ 1 - 0
src/Avalonia.Animation/AnimatorKeyFrame.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using Avalonia.Animation.Animators;
 using Avalonia.Data;
 using Avalonia.Reactive;
 

+ 1 - 1
src/Avalonia.Animation/IterationCount.cs

@@ -44,7 +44,7 @@ namespace Avalonia.Animation
         {
             if (type > IterationType.Infinite)
             {
-                throw new ArgumentException("Invalid value", "type");
+                throw new ArgumentException("Invalid value", nameof(type));
             }
 
             _type = type;

+ 2 - 2
src/Avalonia.Base/Collections/AvaloniaDictionary.cs

@@ -148,7 +148,7 @@ namespace Avalonia.Collections
         {
             if (_inner.TryGetValue(key, out TValue value))
             {
-                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
 
                 if (CollectionChanged != null)
@@ -209,7 +209,7 @@ namespace Avalonia.Collections
 
         private void NotifyAdd(TKey key, TValue value)
         {
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
             
 

+ 1 - 1
src/Avalonia.Base/Collections/AvaloniaList.cs

@@ -511,7 +511,7 @@ namespace Avalonia.Collections
         /// </summary>
         private void NotifyCountChanged()
         {
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
         }
 
         /// <summary>

+ 1 - 0
src/Avalonia.Base/Platform/IAssetLoader.cs

@@ -65,6 +65,7 @@ namespace Avalonia.Platform
         /// Gets all assets of a folder and subfolders that match specified uri.
         /// </summary>
         /// <param name="uri">The URI.</param>
+        /// <param name="baseUri">The base URI.</param>
         /// <returns>All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset</returns>
         IEnumerable<Uri> GetAssets(Uri uri, Uri baseUri);
     }

+ 1 - 1
src/Avalonia.Controls/Calendar/DatePicker.cs

@@ -954,7 +954,7 @@ namespace Avalonia.Controls
                 }
                 else
                 {
-                    var dateValidationError = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException("text", "SelectedDate value is not valid."), text);
+                    var dateValidationError = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException(nameof(text), "SelectedDate value is not valid."), text);
                     OnDateValidationError(dateValidationError);
 
                     if (dateValidationError.ThrowException)

+ 2 - 2
src/Avalonia.Controls/GridLength.cs

@@ -56,12 +56,12 @@ namespace Avalonia.Controls
         {
             if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
             {
-                throw new ArgumentException("Invalid value", "value");
+                throw new ArgumentException("Invalid value", nameof(value));
             }
 
             if (type < GridUnitType.Auto || type > GridUnitType.Star)
             {
-                throw new ArgumentException("Invalid value", "type");
+                throw new ArgumentException("Invalid value", nameof(type));
             }
 
             _type = type;

+ 1 - 1
src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs

@@ -487,7 +487,7 @@ namespace Avalonia.Controls
         {
             if (e == null)
             {
-                throw new ArgumentNullException("e");
+                throw new ArgumentNullException(nameof(e));
             }
 
             var handler = Spinned;

+ 1 - 1
src/Avalonia.Styling/Styling/Setter.cs

@@ -69,7 +69,7 @@ namespace Avalonia.Styling
                 {
                     throw new ArgumentException(
                         "Cannot assign a control to Setter.Value. Wrap the control in a <Template>.",
-                        "value");
+                        nameof(value));
                 }
 
                 _value = value;

+ 1 - 0
src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs

@@ -45,6 +45,7 @@ namespace Avalonia.Skia
         /// <summary>
         /// Create backing Skia surface.
         /// </summary>
+        /// <param name="gpu">GPU.</param>
         /// <param name="width">Width.</param>
         /// <param name="height">Height.</param>
         /// <param name="format">Format.</param>

+ 1 - 0
src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs

@@ -123,6 +123,7 @@ namespace Avalonia.Skia
             /// <summary>
             /// Create framebuffer from given bitmap.
             /// </summary>
+            /// <param name="parent">Parent bitmap impl.</param>
             /// <param name="bitmap">Bitmap.</param>
             public BitmapFramebuffer(WriteableBitmapImpl parent, SKBitmap bitmap)
             {

+ 4 - 2
tests/Avalonia.Animation.UnitTests/Avalonia.Animation.UnitTests.csproj

@@ -1,9 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -22,4 +24,4 @@
   <ItemGroup>
     <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 3 - 1
tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj

@@ -1,9 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />

+ 6 - 1
tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs

@@ -558,7 +558,12 @@ namespace Avalonia.Base.UnitTests.Data.Core
             var result = run();
             result.Item1.Subscribe(x => { });
 
-            GC.Collect();
+            // Mono trickery
+            GC.Collect(2);
+            GC.WaitForPendingFinalizers();
+            GC.WaitForPendingFinalizers();
+            GC.Collect(2);
+            
 
             Assert.Null(result.Item2.Target);
         }

+ 13 - 11
tests/Avalonia.Base.UnitTests/Data/Core/Plugins/DataAnnotationsValidationPluginTests.cs

@@ -4,6 +4,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
+using System.Linq;
 using Avalonia.Data;
 using Avalonia.Data.Core.Plugins;
 using Avalonia.UnitTests;
@@ -86,17 +87,18 @@ namespace Avalonia.Markup.UnitTests.Data.Plugins
             validator.SetValue("123456", BindingPriority.LocalValue);
             validator.SetValue("abcdefghijklm", BindingPriority.LocalValue);
 
-            Assert.Equal(new[]
-            {
-                new BindingNotification(null),
-                new BindingNotification("123456"),
-                new BindingNotification(
-                    new AggregateException(
-                        new ValidationException("The PhoneNumber field is not a valid phone number."),
-                        new ValidationException("The field PhoneNumber must be a string or array type with a maximum length of '10'.")),
-                    BindingErrorType.DataValidationError,
-                    "abcdefghijklm"),
-            }, result);
+            Assert.Equal(3, result.Count);
+            Assert.Equal(new BindingNotification(null), result[0]);
+            Assert.Equal(new BindingNotification("123456"), result[1]);
+            var errorResult = (BindingNotification)result[2];
+            Assert.Equal(BindingErrorType.DataValidationError, errorResult.ErrorType);
+            Assert.Equal("abcdefghijklm", errorResult.Value);
+            var exceptions = ((AggregateException)(errorResult.Error)).InnerExceptions;
+            Assert.True(exceptions.Any(ex =>
+                ex.Message.Contains("The PhoneNumber field is not a valid phone number.")));
+            Assert.True(exceptions.Any(ex =>
+                ex.Message.Contains("The field PhoneNumber must be a string or array type with a maximum length of '10'.")));
+
         }
 
         private class Data

+ 4 - 2
tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj

@@ -1,10 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <LangVersion>latest</LangVersion>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -26,4 +28,4 @@
   <ItemGroup>
     <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 32 - 21
tests/Avalonia.Controls.UnitTests/GridLayoutTests.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System.Collections;
+using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Avalonia.Controls.Utils;
@@ -16,7 +17,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("100, 200, 300", 600d, 600d, new[] { 100d, 200d, 300d })]
         [InlineData("100, 200, 300", 400d, 400d, new[] { 100d, 200d, 100d })]
         public void MeasureArrange_AllPixelLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
@@ -25,7 +26,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("*,2*,3*", 0d, 0d, new[] { 0d, 0d, 0d })]
         [InlineData("*,2*,3*", 600d, 0d, new[] { 100d, 200d, 300d })]
         public void MeasureArrange_AllStarLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
@@ -36,7 +37,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("100,2*,3*", 100d, 100d, new[] { 100d, 0d, 0d })]
         [InlineData("100,2*,3*", 50d, 50d, new[] { 50d, 0d, 0d })]
         public void MeasureArrange_MixStarPixelLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
@@ -49,7 +50,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("100,200,Auto", 100d, 100d, new[] { 100d, 0d, 0d })]
         [InlineData("100,200,Auto", 50d, 50d, new[] { 50d, 0d, 0d })]
         public void MeasureArrange_MixAutoPixelLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
@@ -58,7 +59,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("*,2*,Auto", 0d, 0d, new[] { 0d, 0d, 0d })]
         [InlineData("*,2*,Auto", 600d, 0d, new[] { 200d, 400d, 0d })]
         public void MeasureArrange_MixAutoStarLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
@@ -69,14 +70,24 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("*,200,Auto", 200d, 200d, new[] { 0d, 200d, 0d })]
         [InlineData("*,200,Auto", 100d, 100d, new[] { 0d, 100d, 0d })]
         public void MeasureArrange_MixAutoStarPixelLength_Correct(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             TestRowDefinitionsOnly(length, containerLength, expectedDesiredLength, expectedLengthList);
         }
 
+        
+        /// <summary>
+        /// This is needed because Mono somehow converts double array to object array in attribute metadata
+        /// </summary>
+        static void AssertEqual(IList expected, IReadOnlyList<double> actual)
+        {
+            var conv = expected.Cast<double>().ToArray();
+            Assert.Equal(conv, actual);
+        }
+
         [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local")]
         private static void TestRowDefinitionsOnly(string length, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            double expectedDesiredLength, IList expectedLengthList)
         {
             // Arrange
             var layout = new GridLayout(new RowDefinitions(length));
@@ -84,11 +95,11 @@ namespace Avalonia.Controls.UnitTests
             // Measure - Action & Assert
             var measure = layout.Measure(containerLength);
             Assert.Equal(expectedDesiredLength, measure.DesiredLength);
-            Assert.Equal(expectedLengthList, measure.LengthList);
+            AssertEqual(expectedLengthList, measure.LengthList);
 
             // Arrange - Action & Assert
             var arrange = layout.Arrange(containerLength, measure);
-            Assert.Equal(expectedLengthList, arrange.LengthList);
+            AssertEqual(expectedLengthList, arrange.LengthList);
         }
 
         [Theory]
@@ -99,7 +110,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData("*,2*,Auto", 0d, new[] { Inf, Inf, 0d }, new[] { 0d, 0d, 0d })]
         [InlineData("*,200,Auto", 200d, new[] { Inf, 200d, 0d }, new[] { 0d, 200d, 0d })]
         public void MeasureArrange_InfiniteMeasure_Correct(string length, double expectedDesiredLength,
-            IList<double> expectedMeasureList, IList<double> expectedArrangeList)
+            IList expectedMeasureList, IList expectedArrangeList)
         {
             // Arrange
             var layout = new GridLayout(new RowDefinitions(length));
@@ -107,34 +118,34 @@ namespace Avalonia.Controls.UnitTests
             // Measure - Action & Assert
             var measure = layout.Measure(Inf);
             Assert.Equal(expectedDesiredLength, measure.DesiredLength);
-            Assert.Equal(expectedMeasureList, measure.LengthList);
+            AssertEqual(expectedMeasureList, measure.LengthList);
 
             // Arrange - Action & Assert
             var arrange = layout.Arrange(measure.DesiredLength, measure);
-            Assert.Equal(expectedArrangeList, arrange.LengthList);
+            AssertEqual(expectedArrangeList, arrange.LengthList);
         }
 
         [Theory]
         [InlineData("Auto,*,*", new[] { 100d, 100d, 100d }, 600d, 300d, new[] { 100d, 250d, 250d })]
         public void MeasureArrange_ChildHasSize_Correct(string length,
-            IList<double> childLengthList, double containerLength,
-            double expectedDesiredLength, IList<double> expectedLengthList)
+            IList childLengthList, double containerLength,
+            double expectedDesiredLength, IList expectedLengthList)
         {
             // Arrange
             var lengthList = new ColumnDefinitions(length);
             var layout = new GridLayout(lengthList);
             layout.AppendMeasureConventions(
                 Enumerable.Range(0, lengthList.Count).ToDictionary(x => x, x => (x, 1)),
-                x => childLengthList[x]);
+                x => (double)childLengthList[x]);
 
             // Measure - Action & Assert
             var measure = layout.Measure(containerLength);
             Assert.Equal(expectedDesiredLength, measure.DesiredLength);
-            Assert.Equal(expectedLengthList, measure.LengthList);
+            AssertEqual(expectedLengthList, measure.LengthList);
 
             // Arrange - Action & Assert
             var arrange = layout.Arrange(containerLength, measure);
-            Assert.Equal(expectedLengthList, arrange.LengthList);
+            AssertEqual(expectedLengthList, arrange.LengthList);
         }
 
         [Theory]
@@ -145,7 +156,7 @@ namespace Avalonia.Controls.UnitTests
         [InlineData(160d, 160d, new[] { 100d, 20d, 40d }, new[] { 100d, 20d, 40d })]
         public void MeasureArrange_ChildHasSizeAndHasMultiSpan_Correct(
             double containerLength, double expectedDesiredLength,
-            IList<double> expectedMeasureLengthList, IList<double> expectedArrangeLengthList)
+            IList expectedMeasureLengthList, IList expectedArrangeLengthList)
         {
             var length = "100,*,2*";
             var childLengthList = new[] { 150d, 150d, 150d };
@@ -161,13 +172,13 @@ namespace Avalonia.Controls.UnitTests
             // Measure - Action & Assert
             var measure = layout.Measure(containerLength);
             Assert.Equal(expectedDesiredLength, measure.DesiredLength);
-            Assert.Equal(expectedMeasureLengthList, measure.LengthList);
+            AssertEqual(expectedMeasureLengthList, measure.LengthList);
 
             // Arrange - Action & Assert
             var arrange = layout.Arrange(
                 double.IsInfinity(containerLength) ? measure.DesiredLength : containerLength,
                 measure);
-            Assert.Equal(expectedArrangeLengthList, arrange.LengthList);
+            AssertEqual(expectedArrangeLengthList, arrange.LengthList);
         }
     }
 }

+ 4 - 2
tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj

@@ -1,9 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -22,4 +24,4 @@
   <ItemGroup>
     <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 4 - 1
tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj

@@ -1,9 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
     <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\Microsoft.Reactive.Testing.props" />
@@ -20,4 +23,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 4 - 2
tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj

@@ -1,9 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -23,4 +25,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 4 - 2
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@@ -1,9 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -36,4 +38,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 4 - 2
tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj

@@ -1,10 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
     <OutputType>Library</OutputType>
     <NoWarn>CS0067</NoWarn>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -23,4 +25,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-</Project>
+</Project>

+ 5 - 2
tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj

@@ -1,8 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp2.0</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.0;net47</TargetFrameworks>
+    <OutputType>Library</OutputType>
+    <IsTestProject>true</IsTestProject>
   </PropertyGroup>
   <Import Project="..\..\build\UnitTests.NetCore.targets" />
+  <Import Project="..\..\build\UnitTests.NetFX.props" />
   <Import Project="..\..\build\Moq.props" />
   <Import Project="..\..\build\XUnit.props" />
   <Import Project="..\..\build\Rx.props" />
@@ -21,4 +24,4 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-</Project>
+</Project>