diff --git a/Make.config b/Make.config index 04aa7864c017..e158d3bcad78 100644 --- a/Make.config +++ b/Make.config @@ -260,8 +260,20 @@ MACCATALYST_SDK_VERSION=$(word 1, $(subst ., ,$(MACCATALYST_NUGET_VERSION))).$(w MAX_IOS_DEPLOYMENT_TARGET=$(IOS_SDK_VERSION) MAX_TVOS_DEPLOYMENT_TARGET=$(TVOS_SDK_VERSION) +# Decide which OS version we should run the simulator tests in. +# Note that this may not necessarily match the SDK version, if there are OS releases with no API changes, then there wouldn't necessarily be a corresponding SDK version. +# If the errors below trigger, update the hardcoded Xcode version check (currently 26.3) to use the current Xcode version, and assign the corresponding max simulator versions. +ifeq ($(XCODE_VERSION),26.3) +MAX_IOS_SIMULATOR_VERSION=26.3 +MAX_TVOS_SIMULATOR_VERSION=26.2 +else ifneq ($(XCODE_VERSION),$(IOS_SDK_VERSION)) +$(error Check if a max iOS simulator is different than the current SDK version (this happens when there's a new iOS release, with no API changes so no new SDK)) +else ifneq ($(XCODE_VERSION),$(TVOS_SDK_VERSION)) +$(error Check if a max tvOS simulator is different than the current SDK version (this happens when there's a new tvOS release, with no API changes so no new SDK)) +else MAX_IOS_SIMULATOR_VERSION=$(IOS_SDK_VERSION) MAX_TVOS_SIMULATOR_VERSION=$(TVOS_SDK_VERSION) +endif # Minimum OS versions for running XI/XM apps. MIN_IOS_SDK_VERSION=12.2 diff --git a/NuGet.config b/NuGet.config index 5f5f6bd5b5c6..4b471bb7657b 100644 --- a/NuGet.config +++ b/NuGet.config @@ -12,7 +12,7 @@ - + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index d7cdbae3ff52..a006a9da313a 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -5,41 +5,41 @@ This file should be imported by eng/Versions.props --> - - 10.0.0-beta.26153.116 - 10.0.0-beta.26153.116 + + 10.0.0-beta.26160.113 + 10.0.0-beta.26160.113 0.11.5-alpha.26070.104 - 10.0.0-beta.26153.116 + 10.0.0-beta.26160.113 10.0.3-servicing.26070.104 10.0.3 10.0.3 - 10.0.300-preview.26153.116 + 10.0.300-preview.26160.113 10.0.3 - 10.0.300-preview.26153.116 - + 10.0.300-preview.26160.113 + 26.0.11017 18.5.9227 - 26.2.9001 + 26.2.9002 26.0.11017 18.5.9227 - 26.2.9001 + 26.2.9002 26.0.11017 15.5.9227 - 26.2.9001 + 26.2.9002 26.0.11017 18.5.9227 - 26.2.9001 - + 26.2.9002 + + 11.0.0-prerelease.26160.2 + 18.0.9617 18.0.9617 15.0.9617 18.0.9617 - - 11.0.0-prerelease.26117.1 - + $(MicrosoftDotNetArcadeSdkPackageVersion) $(MicrosoftDotNetBuildTasksFeedPackageVersion) $(MicrosoftDotNetCecilPackageVersion) @@ -50,7 +50,7 @@ This file should be imported by eng/Versions.props $(MicrosoftNETSdkPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftTemplateEngineAuthoringTasksPackageVersion) - + $(MicrosoftiOSSdknet100_260PackageVersion) $(MicrosoftiOSSdknet90_185PackageVersion) $(MicrosoftiOSSdknet90_262PackageVersion) @@ -63,12 +63,12 @@ This file should be imported by eng/Versions.props $(MicrosofttvOSSdknet100_260PackageVersion) $(MicrosofttvOSSdknet90_185PackageVersion) $(MicrosofttvOSSdknet90_262PackageVersion) - + + $(MicrosoftDotNetXHarnessiOSSharedPackageVersion) + $(MicrosoftiOSSdknet90_180PackageVersion) $(MicrosoftMacCatalystSdknet90_180PackageVersion) $(MicrosoftmacOSSdknet90_150PackageVersion) $(MicrosofttvOSSdknet90_180PackageVersion) - - $(MicrosoftDotNetXHarnessiOSSharedPackageVersion) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 12505a21d9dd..2b020df7cab8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/dotnet - cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83 + 37ac471dd9cf9b9b784497fa71dcce9045eb1a78 https://github.com/dotnet/dotnet @@ -60,21 +60,21 @@ 797d30720e5e629d23eb146935da94cb1b61047e - + https://github.com/dotnet/macios - 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb + b34b8d33dfd662493a68b1e443fa04071eebe2b6 - + https://github.com/dotnet/macios - 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb + b34b8d33dfd662493a68b1e443fa04071eebe2b6 - + https://github.com/dotnet/macios - 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb + b34b8d33dfd662493a68b1e443fa04071eebe2b6 - + https://github.com/dotnet/macios - 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb + b34b8d33dfd662493a68b1e443fa04071eebe2b6 @@ -95,25 +95,25 @@ - + https://github.com/dotnet/dotnet - cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83 + 37ac471dd9cf9b9b784497fa71dcce9045eb1a78 - + https://github.com/dotnet/dotnet - cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83 + 37ac471dd9cf9b9b784497fa71dcce9045eb1a78 - + https://github.com/dotnet/dotnet - cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83 + 37ac471dd9cf9b9b784497fa71dcce9045eb1a78 - + https://github.com/dotnet/xharness - 0eeaa60169fe6a95932d29d822e20eb225ce0143 + c32a7777a0f8f7a4fc8d9920d445f5f4b5658d38 - + https://github.com/dotnet/dotnet - cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83 + 37ac471dd9cf9b9b784497fa71dcce9045eb1a78 diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index 5a927b4c7bcb..a9ea99ba6aaa 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -31,7 +31,6 @@ steps: -runtimeSourceFeed https://ci.dot.net/internal -runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)' '$(publishing-dnceng-devdiv-code-r-build-re)' - '$(MaestroAccessToken)' '$(dn-bot-all-orgs-artifact-feeds-rw)' '$(akams-client-id)' '$(microsoft-symbol-server-pat)' diff --git a/global.json b/global.json index fe860c6840a9..e36f010b667e 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.300-preview.26153.116", + "version": "10.0.300-preview.26160.113", "paths": [ "builds/downloads/dotnet", "$host$" @@ -8,9 +8,9 @@ "errorMessage": "The .NET SDK could not be found, please run 'make dotnet -C builds'." }, "tools": { - "dotnet": "10.0.300-preview.26153.116" + "dotnet": "10.0.300-preview.26160.113" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26153.116" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26160.113" } } diff --git a/src/CoreGraphics/CGFont.cs b/src/CoreGraphics/CGFont.cs index b286fe47dd04..71ab4c33e784 100644 --- a/src/CoreGraphics/CGFont.cs +++ b/src/CoreGraphics/CGFont.cs @@ -48,10 +48,10 @@ internal CGFont (NativeHandle handle, bool owns) { } - static CGFont Create (IntPtr handle) + static CGFont? Create (IntPtr handle) { if (handle == IntPtr.Zero) - ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (handle)); + return null; return new CGFont (handle, true); } @@ -74,29 +74,27 @@ protected internal override void Release () [DllImport (Constants.CoreGraphicsLibrary)] extern static /* CGFontRef */ IntPtr CGFontCreateWithDataProvider (/* CGDataProviderRef __nullable */ IntPtr provider); + /// Creates a font from a data provider. /// Data provider that wraps the font. - /// Creates a font from a data provider. - /// The constructed font. - /// - /// - /// You can use this method to create CGFonts from an - /// in-memory representation of the font (for example, to - /// embed binary fonts into your application to prevent easy - /// copying of licensed fonts, or when you fetch the font from - /// a streaming source and do not want to store it on disk). - /// - /// - /// - /// The constructed font, or in case of failure. + /// + /// + /// You can use this method to create instances from an + /// in-memory representation of the font (for example, to + /// embed binary fonts into your application to prevent easy + /// copying of licensed fonts, or when you fetch the font from + /// a streaming source and do not want to store it on disk). + /// + /// + /// - /// - /// + /// + /// public static CGFont? CreateFromProvider (CGDataProvider provider) { // the API accept a `nil` argument but returns `nil`, we take a shortcut (no native call) @@ -111,22 +109,24 @@ protected internal override void Release () [DllImport (Constants.CoreGraphicsLibrary)] extern static /* CGFontRef */ IntPtr CGFontCreateWithFontName (/* CFStringRef __nullable */ IntPtr name); - /// To be added. - /// Creates a new CGFont representing the specified PostScript or full name. - /// To be added. - /// To be added. + /// Creates a new representing the specified PostScript or full name. + /// The PostScript or full name of the font. + /// The new , or if is or no matching font is found. + /// + /// + /// This method looks up a font by its PostScript name or full + /// name. If no font matching is found, + /// the method returns . + /// + /// public static CGFont? CreateWithFontName (string name) { // the API accept a `nil` argument but returns `nil`, we take a shortcut (no native call) // and have a unit tests to make sure this behavior does not change over time if (name is null) return null; - var nameHandle = CFString.CreateNative (name); - try { - return Create (CGFontCreateWithFontName (nameHandle)); - } finally { - CFString.ReleaseNative (nameHandle); - } + var nameHandle = new TransientCFString (name); + return Create (CGFontCreateWithFontName (nameHandle)); } //[DllImport (Constants.CoreGraphicsLibrary)] diff --git a/src/Foundation/NSArray.cs b/src/Foundation/NSArray.cs index 236f64c43321..eb662f40be25 100644 --- a/src/Foundation/NSArray.cs +++ b/src/Foundation/NSArray.cs @@ -675,6 +675,17 @@ static bool TryGetItem (NativeHandle elementHandle, Converter (handle, createObject, NSNullBehavior.Drop, releaseHandle)!; } + /// Returns a strongly-typed C# array from a handle to an NSArray, dropping null elements. + /// Parameter type, determines the kind of array returned. + /// Pointer (handle) to the unmanaged object. + /// How to handle null and NSNull elements in the native array. + /// Whether the native NSArray instance should be released before returning or not. + /// A C# array with the values (excluding null elements). Returns if the handle is . + internal static T []? ArrayFromHandleDropNullElements (NativeHandle handle, NSNullBehavior nsNullElementBehavior, bool releaseHandle = false) where T : class, INativeObject + { + return ArrayFromHandle (handle, (h) => Runtime.GetINativeObject (h, false)!, nsNullElementBehavior, releaseHandle)!; + } + /// Returns a strongly-typed C# array from a handle to an NSArray, dropping null elements and guaranteeing a non-null return value. /// Parameter type, determines the kind of array returned. /// Pointer (handle) to the unmanaged object. @@ -722,55 +733,80 @@ internal static T [] NonNullArrayFromHandleDropNullElements (NativeHandle han return rv!; } -#nullable disable - - static public T [] EnumsFromHandle (NativeHandle handle) where T : struct, IConvertible + /// Returns a C# array of enum values from a handle to an NSArray of NSNumber elements, dropping any null or NSNull elements. + /// The enum type to convert each NSNumber element to. + /// Pointer (handle) to the unmanaged object. + /// A C# array of enum values (excluding null elements), or if the handle is . +#if XAMCORE_5_0 + public static T []? EnumsFromHandle (NativeHandle handle) where T : System.Enum +#else + public static T []? EnumsFromHandle (NativeHandle handle) where T : struct, IConvertible +#endif { - if (handle == NativeHandle.Zero) - return null; +#if !XAMCORE_5_0 if (!typeof (T).IsEnum) throw new ArgumentException ("T must be an enum"); +#endif - var c = GetCount (handle); - T [] ret = new T [c]; + return ArrayFromHandleDropNullElements (handle, (element) => (T) Enum.ToObject (typeof (T), Runtime.GetNSObject (element)?.LongValue ?? 0)); + } - for (uint i = 0; i < c; i++) { - ret [i] = (T) Convert.ChangeType (UnsafeGetItem (handle, i).LongValue, typeof (T)); - } - return ret; + /// Returns a C# array of enum values from a handle to an NSArray of NSNumber elements, dropping null elements and guaranteeing a non-null return value. + /// The enum type to convert each NSNumber element to. + /// Pointer (handle) to the unmanaged object. + /// A C# array of enum values (excluding null elements). Returns an empty array if the handle is . + internal static T [] NonNullEnumsFromHandle (NativeHandle handle) where T : System.Enum + { + return NonNullArrayFromHandleDropNullElements ( + handle, + (element) => (T) Enum.ToObject (typeof (T), Runtime.GetNSObject (element)?.LongValue ?? 0)); } - /// Parameter type, determines the kind of - /// array returned, limited to NSObject and subclasses of it. - /// Handle to an weakly typed NSArray. - /// Returns a strongly-typed C# array of the parametrized type from a weakly typed NSArray. - /// An C# array with the values. - /// - /// Use this method to get a set of NSObject arrays from an NSArray. - /// - /// Creates a strongly-typed C# array from a weakly typed . + /// The element type for the returned array, limited to and subclasses. + /// A weakly typed to convert, or . + /// + /// A C# array of elements, or if + /// is or a conversion error occurs. + /// Elements that are or not compatible with are excluded. + /// + /// + /// + /// (someArray); + /// var values = NSArray.FromArray (someArray); /// ]]> - /// - /// - static public T [] FromArray (NSArray weakArray) where T : NSObject + /// + /// + public static T []? FromArray (NSArray? weakArray) where T : NSObject { - if (weakArray is null || weakArray.Handle == NativeHandle.Zero) - return null; try { - nuint n = weakArray.Count; - T [] ret = new T [n]; - for (nuint i = 0; i < n; i++) { - ret [i] = Runtime.GetNSObject (weakArray.ValueAt (i)); - } - return ret; + var rv = ArrayFromHandleDropNullElements (weakArray.GetHandle (), NSNullBehavior.DropIfIncompatible); + GC.KeepAlive (weakArray); + return rv; } catch { return null; } } + /// + /// Creates a strongly-typed C# array from a weakly typed , + /// dropping null and elements and guaranteeing a non-null return value. + /// + /// The element type for the returned array, limited to and subclasses. + /// A weakly typed to convert, or . + /// + /// A C# array of elements (excluding null and elements). + /// Returns an empty array if is or empty. + /// + internal static T [] ToNonNullArrayDropNullElements (NSArray? weakArray) where T : NSObject + { + var rv = NSArray.NonNullArrayFromHandleDropNullElements (weakArray.GetHandle ()); + GC.KeepAlive (weakArray); + return rv; + } +#nullable disable /// Parameter type, determines the kind of /// array returned, can be either an NSObject, or other /// CoreGraphics data types. diff --git a/src/MetalKit/MTKMesh.cs b/src/MetalKit/MTKMesh.cs index 6186cb436987..9eb1340ee9b0 100644 --- a/src/MetalKit/MTKMesh.cs +++ b/src/MetalKit/MTKMesh.cs @@ -16,7 +16,7 @@ public partial class MTKMesh { /// Creates and returns a new Metal Kit mesh from the supplied Model IO asset. /// To be added. /// To be added. - public static MTKMesh []? FromAsset (MDLAsset asset, IMTLDevice device, out MDLMesh [] sourceMeshes, out NSError error) + public static MTKMesh []? FromAsset (MDLAsset asset, IMTLDevice device, out MDLMesh []? sourceMeshes, out NSError error) { NSArray aret; diff --git a/src/NetworkExtension/NEHotspotEapSettings.cs b/src/NetworkExtension/NEHotspotEapSettings.cs index df97a29e37f7..c000556bea9b 100644 --- a/src/NetworkExtension/NEHotspotEapSettings.cs +++ b/src/NetworkExtension/NEHotspotEapSettings.cs @@ -22,7 +22,7 @@ public partial class NEHotspotEapSettings { /// To be added. public NEHotspotConfigurationEapType [] SupportedEapTypes { get { - return NSArray.EnumsFromHandle (_SupportedEapTypes)!; + return NSArray.NonNullEnumsFromHandle (_SupportedEapTypes); } set { if (value is null) diff --git a/src/UIKit/UIFontDescriptor.cs b/src/UIKit/UIFontDescriptor.cs index 6dfea2f6e079..4b187981160c 100644 --- a/src/UIKit/UIFontDescriptor.cs +++ b/src/UIKit/UIFontDescriptor.cs @@ -532,9 +532,7 @@ public NSCharacterSet? CharacterSet { public UIFontDescriptor [] CascadeList { get { var o = GetObject (UIFontDescriptor.CascadeListAttribute) as NSArray; - if (o is null) - return new UIFontDescriptor [0]; - return NSArray.FromArray (o); + return NSArray.ToNonNullArrayDropNullElements (o); } } diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 8f49ea31dd29..914c35822046 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -4068,7 +4068,7 @@ void GenerateProperty (Type type, PropertyInfo pi, List instance_fields_ print ("return src is null ? null! : new {0}(src);", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType)); } else { if (TypeManager.IsArrayOfWrappedType (pi.PropertyType)) - print ("return NSArray.FromArray<{0}>({1} as NSArray);", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType.GetElementType ()), wrap); + print ("return NSArray.FromArray<{0}>({1} as NSArray){2};", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType.GetElementType ()), wrap, nullable ? "" : "!"); else if (pi.PropertyType.IsValueType) print ("return ({0}) ({1});", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType), wrap); else diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt index 267086a2c81b..cad51eed565b 100644 --- a/tests/cecil-tests/Documentation.KnownFailures.txt +++ b/tests/cecil-tests/Documentation.KnownFailures.txt @@ -11800,7 +11800,6 @@ M:Foundation.INSUrlSessionTaskDelegate.NeedNewBodyStream(Foundation.NSUrlSession M:Foundation.INSUrlSessionWebSocketDelegate.DidClose(Foundation.NSUrlSession,Foundation.NSUrlSessionWebSocketTask,Foundation.NSUrlSessionWebSocketCloseCode,Foundation.NSData) M:Foundation.INSUrlSessionWebSocketDelegate.DidOpen(Foundation.NSUrlSession,Foundation.NSUrlSessionWebSocketTask,System.String) M:Foundation.INSXpcListenerDelegate.ShouldAcceptConnection(Foundation.NSXpcListener,Foundation.NSXpcConnection) -M:Foundation.NSArray.EnumsFromHandle``1(ObjCRuntime.NativeHandle) M:Foundation.NSArray.ToArray M:Foundation.NSArray.ToArray``1 M:Foundation.NSArray`1.ToArray diff --git a/tests/common/test-variations.csproj b/tests/common/test-variations.csproj index 847d55dcbd18..6826b694f495 100644 --- a/tests/common/test-variations.csproj +++ b/tests/common/test-variations.csproj @@ -13,6 +13,7 @@ + @@ -74,6 +75,11 @@ <_TestVariationApplied>true + + static + <_TestVariationApplied>true + + $(AppBundleExtraOptions) --optimize:all static diff --git a/tests/monotouch-test/CoreText/FontTest.cs b/tests/monotouch-test/CoreText/FontTest.cs index ed4513a373d6..b8593972e5c1 100644 --- a/tests/monotouch-test/CoreText/FontTest.cs +++ b/tests/monotouch-test/CoreText/FontTest.cs @@ -7,6 +7,8 @@ // Copyright 2015 Xamarin Inc. All rights reserved. // +using System.Linq; + using CoreGraphics; using CoreText; #if MONOMAC @@ -82,7 +84,7 @@ public void GetLocalizedName () [Test] public void GetGlyphsForCharacters_35048 () { - using (var font = CGFont.CreateWithFontName ("AppleColorEmoji")) + using (var font = CreateAppleColorEmojiFont ()) using (var ctfont = font.ToCTFont ((nfloat) 10.0)) { ushort [] gid = new ushort [2]; Assert.True (ctfont.GetGlyphsForCharacters ("\ud83d\ude00".ToCharArray (), gid), "GetGlyphsForCharacters"); @@ -115,6 +117,14 @@ public void CTFontCreateForStringWithLanguage () } } + static CGFont CreateAppleColorEmojiFont () + { + var font = CGFont.CreateWithFontName ("AppleColorEmoji"); + if (font is null) + Assert.Ignore ("Unable to create the 'AppleColorEmoji' font."); + return font; + } + [Test] public void CTFontCopyNameForGlyph () { @@ -123,7 +133,7 @@ public void CTFontCopyNameForGlyph () using (var ctfont = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default)) Assert.That (ctfont.GetGlyphName ((ushort) 65), Is.EqualTo ("asciicircum"), "1"); - using (var font = CGFont.CreateWithFontName ("AppleColorEmoji")) + using (var font = CreateAppleColorEmojiFont ()) using (var ctfont = font.ToCTFont ((nfloat) 10.0)) Assert.Null (ctfont.GetGlyphName ('\ud83d'), "2"); } @@ -149,7 +159,11 @@ public void GetTypographicBoundsForAdaptiveImageProvider () using var font = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default); using var provider = new AdaptiveImageProvider (); var bounds = font.GetTypographicBoundsForAdaptiveImageProvider (provider); - Assert.AreEqual (new CGRect (0, -3.90625, 13, 16.40625), bounds, "Bounds"); + var candidates = new object [] { + new CGRect (0, -3.90625, 13, 16.40625), + new CGRect (0, -3.90625, 35, 16.40625) + }; + Assert.That (bounds, Is.AnyOf (candidates).Using ((x, y) => x == y), "Bounds"); Assert.AreEqual (0, provider.Count, "#Count"); } diff --git a/tests/monotouch-test/Foundation/NSArray1Test.cs b/tests/monotouch-test/Foundation/NSArray1Test.cs index f58ba7d86c41..3163a6f2a33e 100644 --- a/tests/monotouch-test/Foundation/NSArray1Test.cs +++ b/tests/monotouch-test/Foundation/NSArray1Test.cs @@ -431,6 +431,37 @@ public void FromObjects_WithCount_Null () } } + [Test] + public void EnumsFromHandle_ReturnsNullForZeroHandle () + { + var result = NSArray.EnumsFromHandle (NativeHandle.Zero); + Assert.IsNull (result, "null for zero handle"); + } + + [Test] + public void EnumsFromHandle_Roundtrip () + { + var expected = new [] { + NSComparisonResult.Ascending, + NSComparisonResult.Same, + NSComparisonResult.Descending, + }; + using var n0 = NSNumber.FromNInt ((nint) (long) expected [0]); + using var n1 = NSNumber.FromNInt ((nint) (long) expected [1]); + using var n2 = NSNumber.FromNInt ((nint) (long) expected [2]); + using var array = NSArray.FromNSObjects (n0, n1, n2); + var actual = NSArray.EnumsFromHandle (array.Handle); + Assert.IsNotNull (actual, "not null"); + Assert.That (actual!.Length, Is.EqualTo (3), "Length"); + Assert.That (actual, Is.EqualTo (expected), "values"); + } + + [Test] + public void EnumsFromHandle_ThrowsForNonEnum () + { + Assert.Throws (() => NSArray.EnumsFromHandle (NativeHandle.Zero), "non-enum should throw"); + } + #if false // https://github.com/dotnet/macios/issues/15577 [Test] public void GetDifferenceFromArrayTest () diff --git a/tests/monotouch-test/Metal/MTKMeshTest.cs b/tests/monotouch-test/Metal/MTKMeshTest.cs new file mode 100644 index 000000000000..b1c54f52cd63 --- /dev/null +++ b/tests/monotouch-test/Metal/MTKMeshTest.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Numerics; + +using Foundation; +using Metal; +using MetalKit; +using ModelIO; + +using NUnit.Framework; + +using Vector3i = global::CoreGraphics.NVector3i; + +namespace MonoTouchFixtures.MetalKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MTKMeshTest { + + [Test] + public void FromAsset () + { + var device = MTLDevice.SystemDefault; + if (device is null) + Assert.Inconclusive ("Metal is not supported on this device."); + + using var allocator = new MTKMeshBufferAllocator (device); + using var mesh = MDLMesh.CreateBox (new Vector3 (1, 1, 1), new Vector3i (1, 1, 1), MDLGeometryType.Triangles, false, allocator); + using var asset = new MDLAsset (); + asset.AddObject (mesh); + + var result = MTKMesh.FromAsset (asset, device, out var sourceMeshes, out var error); + + Assert.IsNull (error, "error"); + Assert.IsNotNull (result, "result"); + Assert.That (result!.Length, Is.GreaterThan (0), "result length"); + Assert.IsNotNull (sourceMeshes, "sourceMeshes"); + Assert.AreEqual (result.Length, sourceMeshes!.Length, "sourceMeshes length"); + } + } +} diff --git a/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs b/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs new file mode 100644 index 000000000000..4609cc19862a --- /dev/null +++ b/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#if !__TVOS__ && !__MACOS__ + +using NetworkExtension; + +namespace MonoTouchFixtures.NetworkExtension { + + [TestFixture] + [Preserve (AllMembers = true)] + public class NEHotspotEapSettingsTest { + + [Test] + public void SupportedEapTypes_Default () + { + using var settings = new NEHotspotEapSettings (); + var types = settings.SupportedEapTypes; + Assert.IsNotNull (types, "Default value should not be null"); + Assert.That (types.Length, Is.EqualTo (0), "Default length"); + } + + [Test] + public void SupportedEapTypes_Roundtrip () + { + using var settings = new NEHotspotEapSettings (); + var expected = new [] { + NEHotspotConfigurationEapType.Tls, + NEHotspotConfigurationEapType.Peap, + }; + settings.SupportedEapTypes = expected; + var actual = settings.SupportedEapTypes; + Assert.IsNotNull (actual, "not null"); + Assert.That (actual.Length, Is.EqualTo (2), "Length"); + Assert.That (actual [0], Is.EqualTo (NEHotspotConfigurationEapType.Tls), "[0]"); + Assert.That (actual [1], Is.EqualTo (NEHotspotConfigurationEapType.Peap), "[1]"); + } + + [Test] + public void SupportedEapTypes_AllValues () + { + using var settings = new NEHotspotEapSettings (); + var all = new [] { + NEHotspotConfigurationEapType.Tls, + NEHotspotConfigurationEapType.Ttls, + NEHotspotConfigurationEapType.Peap, + NEHotspotConfigurationEapType.Fast, + }; + settings.SupportedEapTypes = all; + var actual = settings.SupportedEapTypes; + Assert.That (actual.Length, Is.EqualTo (4), "Length"); + Assert.That (actual, Is.EqualTo (all), "All values roundtrip"); + } + + [Test] + public void SupportedEapTypes_SetNull () + { + using var settings = new NEHotspotEapSettings (); + Assert.Throws (() => settings.SupportedEapTypes = null!, "null should throw"); + } + } +} + +#endif // !__TVOS__ && !__MACOS__ diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs index 0df5e8bd75b3..b3ce5aadb8f3 100644 --- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs +++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs @@ -5720,13 +5720,13 @@ public void DecidePolicy (WKWebView webView, WKNavigationAction navigationAction // These classes implement Metal* protocols, so that the generated registrar code includes the corresponding Metal* headers. // https://github.com/dotnet/macios/issues/4422 - class MetalKitTypesInTheSimulator : NSObject, MetalKit.IMTKViewDelegate { - public void Draw (MetalKit.MTKView view) + class MetalKitTypesInTheSimulator : NSObject, global::MetalKit.IMTKViewDelegate { + public void Draw (global::MetalKit.MTKView view) { throw new NotImplementedException (); } - public void DrawableSizeWillChange (MetalKit.MTKView view, CGSize size) + public void DrawableSizeWillChange (global::MetalKit.MTKView view, CGSize size) { throw new NotImplementedException (); } diff --git a/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs index 9841fe1e8946..f6dae5da90b9 100644 --- a/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs +++ b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs @@ -199,6 +199,7 @@ public void DecodeFrameTest () }); Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames"); + Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames"); Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter"); Assert.That (failures, Is.Empty, "Failures"); if (knownDecoderCallbackStatusCount > 0) @@ -238,6 +239,7 @@ public void DecodeFrameMultiImageCallbackTest () }); Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames"); + Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames"); Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter 2"); Assert.That (failures, Is.Empty, "Failures"); } @@ -288,6 +290,7 @@ public void DecodeFrameSetMultiImageCallbackTest () }); Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames"); + Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames"); Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter 2"); Assert.That (failures, Is.Empty, "Failures"); } @@ -323,6 +326,7 @@ public void DecodeFrameCallbackTest () Assert.That (status, Is.EqualTo (VTStatus.Ok), "DecodeFrame"); }); Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames"); + Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames"); Assert.That (frameCallbackCounter, Is.EqualTo (0), "Frame callback counter 3"); Assert.That (inlineCallback, Is.GreaterThan (0), "Frame callback counter 4"); diff --git a/tests/monotouch-test/xamvideotest.mp4 b/tests/monotouch-test/xamvideotest.mp4 index ce6a6378f25c..8478d85c03b9 100644 Binary files a/tests/monotouch-test/xamvideotest.mp4 and b/tests/monotouch-test/xamvideotest.mp4 differ diff --git a/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs b/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs index 3ef19a810e1b..06946f8eee59 100644 --- a/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs +++ b/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs @@ -456,4 +456,175 @@ public struct MyStruct { Assert.That (bindings.AdditionalFiles ["ApiDefinition.cs"].Trim (), Is.EqualTo (expectedApiDefinitionBindings.Trim ()), "Api definition"); Assert.That (bindings.AdditionalFiles ["StructsAndEnums.cs"].Trim (), Is.EqualTo (expectedStructAndEnumsBindings.Trim ()), "Struct and enums"); } + + [Test] + public void Scope_RelativePath () + { + // Verify that --scope with a relative path works correctly + // (the relative path should be resolved to absolute before matching). + var binder = new BindTool (); + var tmpdir = Cache.CreateTemporaryDirectory (); + var subdir = Path.Combine (tmpdir, "headers"); + Directory.CreateDirectory (subdir); + + // Create a header in the scoped directory + var scopedHeader = Path.Combine (subdir, "InScope.h"); + File.WriteAllText (scopedHeader, + """ + @interface InScopeClass { + } + @property int Value; + @end + """); + + // Create an umbrella header that includes both + var mainHeader = Path.Combine (tmpdir, "main.h"); + File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n"); + + binder.SplitDocuments = false; + binder.SourceFile = mainHeader; + binder.OutputDirectory = tmpdir; + + // Use a relative scope path (the bug was that this produced empty output) + var oldCwd = Environment.CurrentDirectory; + try { + Environment.CurrentDirectory = tmpdir; + binder.DirectoriesInScope.Add (Path.GetFullPath ("headers")); + } finally { + Environment.CurrentDirectory = oldCwd; + } + + Configuration.IgnoreIfIgnoredPlatform (binder.Platform); + binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform); + binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory (); + var bindings = binder.BindInOrOut (); + var expectedBindings = +""" +using Foundation; + +// @interface InScopeClass +interface InScopeClass { + // @property int Value; + [Export ("Value")] + int Value { get; set; } +} + +"""; + bindings.AssertSuccess (expectedBindings); + } + + [Test] + public void Scope_FiltersOutOfScopeDeclarations () + { + // Verify that declarations from headers outside the scope directory are not bound. + var binder = new BindTool (); + var tmpdir = Cache.CreateTemporaryDirectory (); + var scopedDir = Path.Combine (tmpdir, "scoped"); + var unscopedDir = Path.Combine (tmpdir, "unscoped"); + Directory.CreateDirectory (scopedDir); + Directory.CreateDirectory (unscopedDir); + + var scopedHeader = Path.Combine (scopedDir, "Scoped.h"); + File.WriteAllText (scopedHeader, + """ + @interface ScopedClass { + } + @property int A; + @end + """); + + var unscopedHeader = Path.Combine (unscopedDir, "Unscoped.h"); + File.WriteAllText (unscopedHeader, + """ + @interface UnscopedClass { + } + @property int B; + @end + """); + + var mainHeader = Path.Combine (tmpdir, "main.h"); + File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n#import \"{unscopedHeader}\"\n"); + + binder.SplitDocuments = false; + binder.SourceFile = mainHeader; + binder.OutputDirectory = tmpdir; + binder.DirectoriesInScope.Add (scopedDir); + Configuration.IgnoreIfIgnoredPlatform (binder.Platform); + binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform); + binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory (); + var bindings = binder.BindInOrOut (); + + // Only ScopedClass should be in the output, not UnscopedClass + var expectedBindings = +""" +using Foundation; + +// @interface ScopedClass +interface ScopedClass { + // @property int A; + [Export ("A")] + int A { get; set; } +} + +"""; + bindings.AssertSuccess (expectedBindings); + } + + [Test] + public void Scope_PrefixDoesNotFalseMatch () + { + // Verify that a scope of "/foo/bar" does not match "/foo/barbaz/header.h" + // (the scope must be a proper directory prefix with separator). + var binder = new BindTool (); + var tmpdir = Cache.CreateTemporaryDirectory (); + var scopedDir = Path.Combine (tmpdir, "scope"); + var falseMatchDir = Path.Combine (tmpdir, "scopeextra"); + Directory.CreateDirectory (scopedDir); + Directory.CreateDirectory (falseMatchDir); + + var scopedHeader = Path.Combine (scopedDir, "Good.h"); + File.WriteAllText (scopedHeader, + """ + @interface GoodClass { + } + @property int X; + @end + """); + + var falseMatchHeader = Path.Combine (falseMatchDir, "Bad.h"); + File.WriteAllText (falseMatchHeader, + """ + @interface BadClass { + } + @property int Y; + @end + """); + + var mainHeader = Path.Combine (tmpdir, "main.h"); + File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n#import \"{falseMatchHeader}\"\n"); + + binder.SplitDocuments = false; + binder.SourceFile = mainHeader; + binder.OutputDirectory = tmpdir; + binder.DirectoriesInScope.Add (scopedDir); + Configuration.IgnoreIfIgnoredPlatform (binder.Platform); + binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform); + binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory (); + var bindings = binder.BindInOrOut (); + + // Only GoodClass should appear (from "scope/"), not BadClass (from "scopeextra/") + var expectedBindings = +""" +using Foundation; + +// @interface GoodClass +interface GoodClass { + // @property int X; + [Export ("X")] + int X { get; set; } +} + +"""; + bindings.AssertSuccess (expectedBindings); + } } diff --git a/tools/devops/automation/scripts/.gitignore b/tools/devops/automation/scripts/.gitignore new file mode 100644 index 000000000000..89923e7760bc --- /dev/null +++ b/tools/devops/automation/scripts/.gitignore @@ -0,0 +1,2 @@ +_provisionator + diff --git a/tools/devops/automation/scripts/provisionator-bootstrap.sh b/tools/devops/automation/scripts/provisionator-bootstrap.sh new file mode 100755 index 000000000000..143cfa4bf75e --- /dev/null +++ b/tools/devops/automation/scripts/provisionator-bootstrap.sh @@ -0,0 +1,131 @@ +#!/bin/bash -e +# shellcheck disable=SC2220,SC2181 +# +# Remove the following GUID if you do not wish for this script self-update: +# D6F71FB5-F2A7-4A62-86D3-10DFE08301CC +# https://github.com/xamarin/provisionator + +while getopts ":t:" opt; do + case "${opt}" in + t) + TOKEN=${OPTARG} + shift 2 + ;; + esac +done + +function selfdir { (cd "$(dirname "$1")"; echo "$PWD"; ) } + +selfdir=$(selfdir "$0") + +channel="${PROVISIONATOR_CHANNEL:-latest}" + +provisionator_sas_token=$AUTH_TOKEN_PROVISIONATOR +if [[ -n $provisionator_sas_token ]]; then + echo "Downloading Provisionator directly from BosStorageMirror Azure blob storage" + base_url="https://bosstoragemirror.blob.core.windows.net/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}" +else + # Grab auth token from Environment first + # Otherwise set to provided option, if available + base_url="https://dl.internalx.com/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}" + auth_token=$AUTH_TOKEN_GITHUB_COM + if [[ -z $auth_token ]]; then + echo "Setting auth_token to input token and not AUTH_TOKEN_GITHUB_COM" + auth_token=$TOKEN + fi + if [[ -z $auth_token ]]; then + echo "WARNING: Please set AUTH_TOKEN_GITHUB_COM to a GitHub PAT before running provisionator or run provisionator.sh -t ..." + echo "At a future point, Provisionator will not be able to bootstrap without the PAT set properly" + base_url="https://bosstoragemirror.blob.core.windows.net/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}" + fi +fi + +latest_version_url="${base_url}/version" + +if [[ -n $provisionator_sas_token ]]; then + echo "latest_version_url: Appending SAS token" + latest_version_url="${latest_version_url}?${provisionator_sas_token}" +fi + +archive_name="provisionator.osx.10.11-x64.zip" +archive_path="${selfdir}/${archive_name}" +archive_extract_path="${selfdir}/_provisionator" +archive_url="${base_url}/${archive_name}" +if [[ -n $provisionator_sas_token ]]; then + echo "archive_url: Appending SAS token" + archive_url="${archive_url}?${provisionator_sas_token}" +fi + +binary_path="${archive_extract_path}/provisionator" +pk_path="${archive_extract_path}/pk" + +set +e + +# Double brackets are required for the following condition to evaulate as expected +if [[ -z $auth_token ]] || [[ -n $provisionator_sas_token ]]; then + if [[ -n $provisionator_sas_token ]]; then + echo "Fetching latest version with SAS token" + else + echo "Fetching latest version without auth token" + fi + latest_version="$(curl -fsL "${latest_version_url}")" +else + echo "Fetching latest version with auth token" + latest_version="$(curl -fsL -H "Authorization: token ${auth_token}" "${latest_version_url}")" +fi +if [[ $? != 0 ]]; then + echo "Unable to determine latest version from ${latest_version_url}" + echo "Please check to make sure a valid GitHub PAT was provided" + exit 1 +fi +set -e + +function update_in_place { + echo "Downloading Provisionator $latest_version..." + local progress_type="-s" + tty -s && progress_type="-#" + if [[ -z $auth_token ]] || [[ -n $provisionator_sas_token ]]; then + curl -fL $progress_type -o "$archive_path" "$archive_url" + else + curl -fLH "Authorization: token ${auth_token}" $progress_type -o "$archive_path" "$archive_url" + fi + rm -rf "$archive_extract_path" + unzip -q -o -d "$archive_extract_path" "$archive_path" + rm -f "$archive_path" +} + +if [[ -f "$binary_path" ]]; then + chmod +x "$binary_path" + current_version="$("$binary_path" -version 2>&1 || true)" + if [[ "$latest_version" != "$current_version" ]]; then + update_in_place + fi +else + update_in_place +fi + +# Check for the pk (PackageKitTool) binary, which should be included in the provisionator macOS ZIP package +if [[ "$OSTYPE" == "darwin"* ]]; then + echo "Checking for PackageKitTool (pk) binary..." + if [[ -f "$pk_path" ]]; then + echo "PackageKitTool (pk) binary found: ${pk_path}" + echo "chmod +x ${pk_path}" + chmod +x "$pk_path" + else + echo "ERROR: pk file not found: ${pk_path}" + exit 5 + fi +fi + +# Opt out of macOS backward compat so correct Big Sur OS versions can be obtained. +# More info https://github.com/ziglang/zig/issues/7569 +export SYSTEM_VERSION_COMPAT=0 + +# TODO: The executable permission should be applied here. However, since this script is reflective of production scripts used by other clients/teams avoid modifying the executable permission here. +# A reason to avoid this is that the executable permission is expected to be preserved in the ZIP file produced by the ClientTools.Provisionator build pipeline +# CONSIDER: A possible follow up item would be to go update all the production scripts to apply the executable permission here to ensure the provisionator binary has the executable permission set +# This may also involve updating the Provisionator Azure DevOps provisionator task to ensure it applies the executable attribute after ZIP extraction +# https://devdiv.visualstudio.com/Engineering/_git/xamarin-azdev-extension?path=/provisionator-task +# echo "Applying executable attribute: ${binary_path}" +# chmod +x "$binary_path" +exec caffeinate "$binary_path" "$@" diff --git a/tools/devops/automation/templates/build/build.yml b/tools/devops/automation/templates/build/build.yml index d3d9951de246..ae746a2d4776 100644 --- a/tools/devops/automation/templates/build/build.yml +++ b/tools/devops/automation/templates/build/build.yml @@ -85,14 +85,12 @@ steps: make -C $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops provisioning displayName: 'Generate provisionator files.' - - task: xamops.azdevex.provisionator-task.provisionator@2 - displayName: 'Provision Products & Frameworks' - inputs: + - template: ../common/provision.yml + parameters: provisioning_script: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/build-provisioning.csx - provisioning_extra_args: '-vvvv' - github_token: ${{ parameters.gitHubToken }} - timeoutInMinutes: 250 - retryCountOnTaskFailure: ${{ parameters.retryCount }} # mono does give issues sometimes to download, we will retry + displayName: 'Provision Products & Frameworks' + provisionatorChannel: $(PROVISIONATOR_CHANNEL) + retryCount: ${{ parameters.retryCount }} # mono does give issues sometimes to download, we will retry - bash: | set -x diff --git a/tools/devops/automation/templates/common/provision.yml b/tools/devops/automation/templates/common/provision.yml new file mode 100644 index 000000000000..6424ffd2103d --- /dev/null +++ b/tools/devops/automation/templates/common/provision.yml @@ -0,0 +1,116 @@ +# yamllint disable rule:line-length +# Template to run provisionator via the bootstrap script with BosStorageMirror SAS token auth. +# This replaces the xamops.azdevex.provisionator-task.provisionator@3 task to avoid +# dl.internalx.com timeout issues under concurrent load. + +parameters: + - name: provisioning_script + type: string + + - name: displayName + type: string + default: 'Provisionator' + + - name: provisionatorChannel + type: string + default: 'latest' + + - name: provisioning_extra_args + type: string + default: '-vvvv' + + - name: timeoutInMinutes + type: number + default: 250 + + - name: retryCount + type: number + default: 0 + + - name: enabled + type: boolean + default: true + +steps: + - task: AzureCLI@2 + displayName: 'Generate BosStorageMirror SAS tokens' + condition: and(succeeded(), ${{ parameters.enabled }}) + inputs: + azureSubscription: 'Xamarin - RelEng (BosStorageMirror-Contributor-MI)' + scriptType: 'bash' + scriptLocation: 'inlineScript' + failOnStandardError: true + inlineScript: | + set -euo pipefail + + storage_account="bosstoragemirror" + + # macOS/BSD date syntax for expiry calculation + start_time="$(date -u '+%Y-%m-%dT%H:%MZ')" + prov_expiry="$(date -u -v+20M '+%Y-%m-%dT%H:%MZ')" + files_expiry="$(date -u -v+3H '+%Y-%m-%dT%H:%MZ')" + + echo "Generating provisionator SAS token (expires $prov_expiry)..." + sas_provisionator="$(az storage container generate-sas \ + --account-name "$storage_account" \ + --name provisionator \ + --permissions r \ + --start "$start_time" \ + --expiry "$prov_expiry" \ + --https-only \ + --as-user \ + --auth-mode login \ + -o tsv)" + + if [[ -z "$sas_provisionator" || ${#sas_provisionator} -le 16 ]]; then + echo "ERROR: Failed to generate SAS token for BosStorageMirror provisionator container" + exit 1 + fi + + echo "Generating internal-files SAS token (expires $files_expiry)..." + sas_internal_files="$(az storage container generate-sas \ + --account-name "$storage_account" \ + --name internal-files \ + --permissions r \ + --start "$start_time" \ + --expiry "$files_expiry" \ + --https-only \ + --as-user \ + --auth-mode login \ + -o tsv)" + + if [[ -z "$sas_internal_files" || ${#sas_internal_files} -le 16 ]]; then + echo "ERROR: Failed to generate SAS token for BosStorageMirror internal-files container" + exit 1 + fi + + prov_hint="${sas_provisionator:0:8}...${sas_provisionator: -8}" + files_hint="${sas_internal_files:0:8}...${sas_internal_files: -8}" + + echo "sasTokenProvisionator [hint]: $prov_hint" + echo "sasToken [hint]: $files_hint" + + echo "##vso[task.setvariable variable=Provisionator.SASToken;issecret=true]$sas_provisionator" + echo "##vso[task.setvariable variable=Provisionator.SASTokenHint]$prov_hint" + echo "##vso[task.setvariable variable=BosStorageMirror.SASToken;issecret=true]$sas_internal_files" + echo "##vso[task.setvariable variable=BosStorageMirror.SASTokenHint]$files_hint" + + - bash: | + set -x + set -e + + BOOTSTRAP_SCRIPT="$(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/automation/scripts/provisionator-bootstrap.sh" + chmod +x "$BOOTSTRAP_SCRIPT" + + echo "Provisionator channel: ${PROVISIONATOR_CHANNEL}" + echo "Provisioning script: ${{ parameters.provisioning_script }}" + + "$BOOTSTRAP_SCRIPT" ${{ parameters.provisioning_script }} ${{ parameters.provisioning_extra_args }} || exit 2 + displayName: '${{ parameters.displayName }}' + condition: and(succeeded(), ${{ parameters.enabled }}) + env: + PROVISIONATOR_CHANNEL: ${{ parameters.provisionatorChannel }} + AUTH_TOKEN_PROVISIONATOR: $(Provisionator.SASToken) + AUTH_TOKEN_BOSSTORAGEMIRROR: $(BosStorageMirror.SASToken) + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + retryCountOnTaskFailure: ${{ parameters.retryCount }} diff --git a/tools/devops/automation/templates/mac/build.yml b/tools/devops/automation/templates/mac/build.yml index 12cd12a3d0b4..fd4bcfacc0c4 100644 --- a/tools/devops/automation/templates/mac/build.yml +++ b/tools/devops/automation/templates/mac/build.yml @@ -104,14 +104,13 @@ steps: displayName: 'Set VM Vendor' -- task: xamops.azdevex.provisionator-task.provisionator@2 - displayName: 'Provision Brew components' - inputs: +- template: ../common/provision.yml + parameters: provisioning_script: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/provision-brew-packages.csx - provisioning_extra_args: '-vvvv' - github_token: $(Github.Token) - timeoutInMinutes: 30 - enabled: false + displayName: 'Provision Brew components' + provisionatorChannel: $(PROVISIONATOR_CHANNEL) + timeoutInMinutes: 30 + enabled: false - bash: | sudo rm -Rf $(Build.SourcesDirectory)/package diff --git a/tools/devops/automation/templates/tests/build.yml b/tools/devops/automation/templates/tests/build.yml index 9d94572b96d0..1eacbac94c70 100644 --- a/tools/devops/automation/templates/tests/build.yml +++ b/tools/devops/automation/templates/tests/build.yml @@ -203,13 +203,11 @@ steps: condition: ${{ parameters.clearProvisionatorCache }} # Use the provisionator to install the test dependencies. Those have been generated in the 'Generate Provisionator csx file' step. -- task: xamops.azdevex.provisionator-task.provisionator@2 - displayName: 'Provisionator dependencies' - inputs: +- template: ../common/provision.yml + parameters: provisioning_script: $(System.DefaultWorkingDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/build-provisioning.csx - provisioning_extra_args: '-vvvv' - github_token: ${{ parameters.gitHubToken }} - timeoutInMinutes: 250 + displayName: 'Provisionator dependencies' + provisionatorChannel: $(PROVISIONATOR_CHANNEL) - bash: | set -x diff --git a/tools/devops/automation/templates/windows/reserve-mac.yml b/tools/devops/automation/templates/windows/reserve-mac.yml index c0e2c9ae0ae8..9e24069e0af6 100644 --- a/tools/devops/automation/templates/windows/reserve-mac.yml +++ b/tools/devops/automation/templates/windows/reserve-mac.yml @@ -99,13 +99,11 @@ steps: rm -f ~/Library/Preferences/Xamarin/Settings.plist displayName: 'Clear old Xcode settings' -- task: xamops.azdevex.provisionator-task.provisionator@2 - displayName: 'Provision Xcode' - inputs: +- template: ../common/provision.yml + parameters: provisioning_script: $(System.DefaultWorkingDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/provision-xcode.csx - provisioning_extra_args: '-vvvv' - github_token: ${{ parameters.gitHubToken }} - timeoutInMinutes: 250 + displayName: 'Provision Xcode' + provisionatorChannel: $(PROVISIONATOR_CHANNEL) - bash: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/system-dependencies.sh --ignore-visual-studio --ignore-shellcheck --ignore-yamllint --provision-simulators --ignore-xcode-components displayName: 'Provision simulators' diff --git a/tools/dotnet-linker/Makefile b/tools/dotnet-linker/Makefile index 033e0b101db4..eaabacd81b23 100644 --- a/tools/dotnet-linker/Makefile +++ b/tools/dotnet-linker/Makefile @@ -16,6 +16,7 @@ DOTNET_DIRECTORIES += \ # dotnet-linker.csproj.inc contains the dotnet_linker_dependencies variable used to determine if mtouch needs to be rebuilt or not. dotnet-linker.csproj.inc: export BUILD_VERBOSITY=$(DOTNET_BUILD_VERBOSITY) +dotnet-linker.csproj.inc: export DOTNET:=$(DOTNET) dotnet-linker.csproj.inc: dotnet-linker.csproj -include dotnet-linker.csproj.inc diff --git a/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs b/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs index 8406602d1bcf..7e76452e4acd 100644 --- a/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs +++ b/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs @@ -154,7 +154,12 @@ bool IsInScope (Decl? decl) if (string.IsNullOrEmpty (fn)) return true; foreach (var dir in DirectoriesInScope) { - if (fn.StartsWith (dir, StringComparison.Ordinal)) + // Ensure the scope directory ends with a directory separator so that + // a scope of "/foo/bar" doesn't falsely match "/foo/barbaz/header.h". + var normalizedDir = dir.EndsWith (Path.DirectorySeparatorChar) || dir.EndsWith (Path.AltDirectorySeparatorChar) + ? dir + : dir + Path.DirectorySeparatorChar; + if (fn.StartsWith (normalizedDir, StringComparison.Ordinal)) return true; } diff --git a/tools/sharpie/Sharpie.Bind/Tools.cs b/tools/sharpie/Sharpie.Bind/Tools.cs index 1fd06094bfb4..3381d62a0962 100644 --- a/tools/sharpie/Sharpie.Bind/Tools.cs +++ b/tools/sharpie/Sharpie.Bind/Tools.cs @@ -33,7 +33,7 @@ public static int Bind (string [] arguments) { "s|sdk=", "Target SDK.", v => binder.Sdk = v }, { "f|framework=", "The input framework to bind. Implies setting the scope (--scope) to the framework, setting the namespace (--namespace) to the name of the framework, and no other sources/headers can be specified. If the framework provides an 'Info.plist' with SDK information (DTSDKName), the '-sdk' option will be implied as well (if not manually specified).", v => binder.SourceFramework = v }, { "header=", "The input header file to bind. This can also be a .framework directory.", v => binder.SourceFile = v }, - { "scope=", "Restrict following #include and #import directives declared in header files to within the specified DIR directory.", v => binder.DirectoriesInScope.Add (v) }, + { "scope=", "Restrict following #include and #import directives declared in header files to within the specified DIR directory.", v => binder.DirectoriesInScope.Add (Path.GetFullPath (v)) }, { "c|clang", "All arguments after this argument are not processed by Objective Sharpie and are proxied directly to Clang.", v => { } }, { "clang-resource-dir=", "Specify the Clang resource directory.", v => binder.ClangResourceDirectory = v }, { "platform-assembly=", "Specify the platform assembly to use for binding.", v => binder.PlatformAssembly = v },