From 0e42551756a07952e7bd5f1a1172d25484eea9c9 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 4 Dec 2023 08:25:07 +0100 Subject: [PATCH] [tests] Port the ModelMustBeProtocol test from monotouch-test to cecil-test. (#19561) It uses reflection, so it upsets NativeAOT, so just move it to cecil-test instead. This will make it run faster, and also more predictable (it's supposed to check all types, but types in monotouch-test may have been linked away). Ref: https://github.com/dotnet/runtime/issues/95444 --- tests/cecil-tests/AttributeTest.cs | 51 ++++++++++++++++++ .../Foundation/ProtocolAttributeTest.cs | 52 ------------------- 2 files changed, 51 insertions(+), 52 deletions(-) delete mode 100644 tests/monotouch-test/Foundation/ProtocolAttributeTest.cs diff --git a/tests/cecil-tests/AttributeTest.cs b/tests/cecil-tests/AttributeTest.cs index 84c45a3faf..f3f8b37214 100644 --- a/tests/cecil-tests/AttributeTest.cs +++ b/tests/cecil-tests/AttributeTest.cs @@ -583,5 +583,56 @@ namespace Cecil.Tests { bool IsAvailabilityAttribute (CustomAttribute attribute) => IsSupportedAttribute (attribute) || attribute.AttributeType.Name == "UnsupportedOSPlatformAttribute"; bool IsSupportedAttribute (CustomAttribute attribute) => attribute.AttributeType.Name == "SupportedOSPlatformAttribute"; + + [TestCaseSource (typeof (Helper), nameof (Helper.NetPlatformAssemblyDefinitions))] + public void ModelMustBeProtocol (AssemblyInfo info) + { + // Verify that all types with a [Model] attribute must also have a [Protocol] attribute. + // Exception: If the type in question has a [Register] attribute with IsWrapper = false, then that's OK. + var failures = new HashSet (); + var typesWithModelAttribute = 0; + var typesWithProtocolAttribute = 0; + var assembly = info.Assembly; + + foreach (var type in assembly.EnumerateTypes ()) { + if (!type.HasCustomAttributes) + continue; + + var attributes = type.CustomAttributes; + + if (!attributes.Any (v => v.AttributeType.Is ("Foundation", "ModelAttribute"))) + continue; + typesWithModelAttribute++; + + if (attributes.Any (v => v.AttributeType.Is ("Foundation", "ProtocolAttribute"))) { + typesWithProtocolAttribute++; + continue; + } + + var registerAttribute = attributes.SingleOrDefault (v => v.AttributeType.Is ("Foundation", "RegisterAttribute")); + if (registerAttribute is not null && !GetIsWrapper (registerAttribute)) + continue; + + failures.Add ($"The type {type.FullName} has a [Model] attribute, but no [Protocol] attribute."); + } + + Assert.That (failures, Is.Empty, "Failures"); + Assert.That (typesWithModelAttribute, Is.GreaterThan (0), "No types with the [Model] attribute?"); + Assert.That (typesWithProtocolAttribute, Is.GreaterThan (0), "No types with the [Protocol] attribute?"); + + static bool GetIsWrapper (CustomAttribute attrib) + { + // .ctor (string name, bool isWrapper) + if (attrib.ConstructorArguments.Count == 2) + return (bool) attrib.ConstructorArguments [1].Value; + + // public bool IsWrapper { get; set; } + foreach (var field in attrib.Fields) { + if (field.Name == "IsWrapper") + return (bool) field.Argument.Value; + } + return false; + } + } } } diff --git a/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs b/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs deleted file mode 100644 index f814267f66..0000000000 --- a/tests/monotouch-test/Foundation/ProtocolAttributeTest.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Unit tests for ProtocolAttribute (yeah, really!) -// -// Authors: -// Rolf Bjarne Kvinge -// -// Copyright 2013 Xamarin Inc. All rights reserved. -// - -using System; -using Foundation; -using ObjCRuntime; -using NUnit.Framework; - -namespace MonoTouchFixtures.Foundation { - - [TestFixture] - [Preserve (AllMembers = true)] - public class ProtocolAttributeTest { - - [Test] - public void ModelMustBeProtocol () - { - int count = 0; - - // - // Note that [Model], but no [Protocol] is not a universal truth (so it's - // not enforced in the generator), but it should be true for monotouch.dll. - // - - foreach (var type in typeof (NSObject).Assembly.GetTypes ()) { - if (!type.IsSubclassOf (typeof (NSObject))) - continue; - - var register = (RegisterAttribute) Attribute.GetCustomAttribute (type, typeof (RegisterAttribute), false); - if (register is not null && !register.IsWrapper) - continue; - - if (Attribute.GetCustomAttribute (type, typeof (ModelAttribute), false) is null) - continue; - - if (Attribute.GetCustomAttribute (type, typeof (ProtocolAttribute), false) is null) { - Console.WriteLine ("{0} must have a [Protocol] attribute if it has a [Model] attribute", type.FullName); - count++; - } - } - - if (count > 0) - Assert.Fail ("Found {0} types with a [Model] attribute (and no [Register(false)] attribute signalling that they're not wrapper types), but without a [Protocol] attribute.", count); - } - } -}