xamarin-macios/tests/introspection/ApiWeakPropertyTest.cs

122 строки
3.7 KiB
C#
Исходник Обычный вид История

using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework;
using Foundation;
using ObjCRuntime;
namespace Introspection {
[Preserve (AllMembers = true)]
public abstract class ApiWeakPropertyTest : ApiBaseTest {
/// <summary>
/// Override if you want to skip testing the specified type.
/// </summary>
/// <param name="type">Type to be tested</param>
protected virtual bool Skip (Type type)
{
switch (type.Name) {
2022-06-27 17:01:29 +03:00
case "LinkWithAttribute": // LinkWithAttribute.WeakFrameworks
return true;
// Xcode 14, this properties have been added as a compat layer
case "GKPeerPickerController":
return true;
}
[mtouch] Add `force-rejected-types-removal` optimization (#8009) This optimization can be enabled when it's not possible to use the managed linker (e.g. **Don't link**) or when the managed linker cannot remove references to deprecated types that would cause an application to be rejected by Apple. References to the existing types will be renamed, e.g. `UIWebView` to `DeprecatedWebView`, in every assemblies. The type definition is also renamed (for validity) and all custom attributes on the types and their members will be removed. Code inside the members will be replaced with a `throw new NotSupportedException ();`. The msbuild test app `MyReleaseBuild` has been updated to test that the optimization is working as expected (device builds are slow so reusing this test has little impact in test time). Basically the test ensure that `UIWebView` is used and cannot be removed by the compiler (optimization) or the managed linker (since it's referenced). Since the optimization is enabled then we can `grep` then final `.app` directory to ensure there's no mention of `UIWebView` inside any of the files that would be submitted. The application can be run, by itself, and will turn green if OK, red if `DeprecatedWebView` can't be found (skeleton replacement for `UIWebView`) or orange if a `NotSupportedException` is thrown. Finally introspection tests have been updated to skip over the deprecated (and renamed) types. It should not be an issue right now, since this optimization is not enabled by default, but it made testing easier.
2020-03-02 17:20:29 +03:00
return SkipDueToRejectedTypes (type);
}
/// <summary>
/// Override if you want to skip testing the specified property.
/// </summary>
/// <param name="property">Property candidate.</param>
protected virtual bool Skip (PropertyInfo property)
{
switch (property.Name) {
// the selector starts with `weak`
case "WeakRelatedUniqueIdentifier":
return property.DeclaringType.Name == "CSSearchableItemAttributeSet";
// this is a weakly typed API (not a weak reference) with a [NotImplemented] so there's no [Export]
case "WeakSignificantEvent":
return property.DeclaringType.Name == "HMSignificantTimeEvent";
case "WeakMeasurementUnits":
// this is a weakly typed API (not a weak reference), so there's no [Export]
return property.DeclaringType.Name == "NSRulerView";
#if !XAMCORE_5_0
case "WeakEnabled":
// this is from a strongly typed dictionary, and "Weak" here means nullable (bool) as opposed to a plain bool - and this is fixed in XAMCORE_5_0 so that the Enabled property is nullable and thus we won't need the WeakEnabled version anymore.
return property.DeclaringType.Name == "CTFontDescriptorAttributes";
#endif
}
return false;
}
[Test]
public void WeakPropertiesHaveArgumentSemantic ()
{
var failed_properties = new List<string> ();
Errors = 0;
int c = 0, n = 0;
foreach (Type t in Assembly.GetTypes ()) {
if (Skip (t) || SkipDueToAttribute (t))
continue;
if (LogProgress)
Console.WriteLine ("{0}. {1}", c++, t.FullName);
foreach (var p in t.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
// looking for properties with setters only
if (!p.CanWrite)
continue;
if (SkipDueToAttribute (p))
continue;
if (Skip (p))
continue;
string name = p.Name;
if (!name.StartsWith ("Weak", StringComparison.Ordinal))
continue;
string error;
if (CheckArgumentSemantic (p.GetMethod, out error)) {
ReportError (error);
failed_properties.Add (p.ToString ());
}
if (CheckArgumentSemantic (p.SetMethod, out error)) {
ReportError (error);
failed_properties.Add (p.ToString ());
}
n++;
}
}
Assert.AreEqual (0, Errors, "{0} errors found in {1} fields validated: {2}", Errors, n, string.Join (", ", failed_properties));
}
bool CheckArgumentSemantic (MethodInfo meth, out string error)
{
error = null;
var export = meth.GetCustomAttribute<ExportAttribute> ();
if (export is null) {
error = String.Format ("{0}.{1} has no [Export]", meth.DeclaringType.FullName, meth.Name);
return true;
}
switch (export.ArgumentSemantic) {
case ArgumentSemantic.Assign: // Also case ArgumentSemantic.UnsafeUnretained:
case ArgumentSemantic.Copy:
case ArgumentSemantic.Retain: // case ArgumentSemantic.Strong:
case ArgumentSemantic.Weak:
return false;
default:
error = String.Format ("{0}.{1} has incorrect ArgumentSemantics: {2}", meth.DeclaringType.FullName, meth.Name, export.ArgumentSemantic);
return true;
}
}
}
}