|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Windows.Markup;
using System.Xaml.Schema;
using System.Xaml.Tests.Common;
using System.Xml.Serialization;
using Xunit;
namespace System.Xaml.Tests
{
public class XamlTypeTests
{
public static IEnumerable<object?[]> Ctor_String_String_XamlTypeNames_XamlSchemaContext_TestData()
{
yield return new object?[] { "", "", null, new XamlSchemaContext() };
yield return new object?[] { "unknownTypeNamespace", "unknownTypeName", Array.Empty<XamlType>(), new XamlSchemaContext() };
yield return new object?[] { "unknownTypeNamespace", "unknownTypeName", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext() };
}
[Theory]
[MemberData(nameof(Ctor_String_String_XamlTypeNames_XamlSchemaContext_TestData))]
public void Ctor_String_String_XamlTypeNames_XamlSchemaContext(string unknownTypeNamespace, string unknownTypeName, IList<XamlType> typeArguments, XamlSchemaContext schemaContext)
{
var type = new XamlType(unknownTypeNamespace, unknownTypeName, typeArguments, schemaContext);
Assert.Equal(new string[] { unknownTypeNamespace }, type.GetXamlNamespaces());
Assert.Equal(unknownTypeName, type.Name);
Assert.Equal(typeArguments != null && typeArguments.Count > 0 ? typeArguments : null, type.TypeArguments);
Assert.Equal(schemaContext, type.SchemaContext);
Assert.True(type.IsUnknown);
Assert.Equal(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
[Fact]
public void Ctor_NullUnknownTypeNamespace_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("unknownTypeNamespace", () => new XamlType(null, "unknownTypeName", Array.Empty<XamlType>(), new XamlSchemaContext()));
}
[Fact]
public void Ctor_NullUnknownTypeName_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("unknownTypeName", () => new XamlType("unknownTypeNamespace", null, Array.Empty<XamlType>(), new XamlSchemaContext()));
}
public static IEnumerable<object?[]> Ctor_String_XamlTypeNames_XamlSchemaContext_TestData()
{
yield return new object?[] { "", null, new XamlSchemaContext() };
}
[Theory]
[MemberData(nameof(Ctor_String_XamlTypeNames_XamlSchemaContext_TestData))]
public void Ctor_String_XamlTypeNames_XamlSchemaContext(string typeName, IList<XamlType?>? typeArguments, XamlSchemaContext schemaContext)
{
var type = new SubXamlType(typeName, typeArguments, schemaContext);
Assert.Equal(new string[] { "" }, type.GetXamlNamespaces());
Assert.Equal(typeName, type.Name);
Assert.Equal(typeArguments != null && typeArguments.Count > 0 ? typeArguments : null, type.TypeArguments);
Assert.Equal(schemaContext, type.SchemaContext);
Assert.True(type.IsUnknown);
Assert.Equal(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
[Fact]
public void Ctor_NullTypeName_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("typeName", () => new SubXamlType(null!, Array.Empty<XamlType>(), new XamlSchemaContext()));
}
public static IEnumerable<object?[]> Ctor_Type_XamlSchemaContext_TestData()
{
yield return new object?[] { typeof(int), new XamlSchemaContext(), "Int32", null };
yield return new object?[] { typeof(NestedClass), new XamlSchemaContext(), "XamlTypeTests+NestedClass", null };
yield return new object?[] { typeof(List<int>), new XamlSchemaContext(), "List", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
yield return new object?[] { typeof(List<int>[][]), new XamlSchemaContext(), "List[][]", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
}
[Theory]
[MemberData(nameof(Ctor_Type_XamlSchemaContext_TestData))]
public void Ctor_Type_XamlSchemaContext(Type underlyingType, XamlSchemaContext schemaContext, string expectedName, XamlType[] expectedTypeArguments)
{
var type = new XamlType(underlyingType, schemaContext);
Assert.Equal(expectedName, type.Name);
Assert.Equal(expectedTypeArguments, type.TypeArguments);
Assert.Equal(schemaContext, type.SchemaContext);
Assert.False(type.IsUnknown);
Assert.NotEqual(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
public static IEnumerable<object?[]> Ctor_Type_XamlSchemaContext_XamlTypeInvoker_TestData()
{
yield return new object?[] { typeof(int), new XamlSchemaContext(), null, "Int32", null };
yield return new object?[] { typeof(NestedClass), new XamlSchemaContext(), new XamlTypeInvoker(new XamlType(typeof(int), new XamlSchemaContext())), "XamlTypeTests+NestedClass", null };
yield return new object?[] { typeof(List<int>), new XamlSchemaContext(), XamlTypeInvoker.UnknownInvoker, "List", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
yield return new object?[] { typeof(List<int>[][]), new XamlSchemaContext(), null, "List[][]", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
}
[Theory]
[MemberData(nameof(Ctor_Type_XamlSchemaContext_XamlTypeInvoker_TestData))]
public void Ctor_Type_XamlSchemaContext_XamlTypeInvoker(Type underlyingType, XamlSchemaContext schemaContext, XamlTypeInvoker invoker, string expectedName, XamlType[] expectedTypeArguments)
{
var type = new XamlType(underlyingType, schemaContext, invoker);
Assert.Equal(expectedName, type.Name);
Assert.Equal(expectedTypeArguments, type.TypeArguments);
Assert.Equal(schemaContext, type.SchemaContext);
Assert.False(type.IsUnknown);
if (invoker == null)
{
Assert.NotNull(type.Invoker);
Assert.NotEqual(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
else
{
Assert.Equal(invoker, type.Invoker);
}
}
[Fact]
public void Ctor_NullUnderlyingType_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("underlyingType", () => new XamlType(null, new XamlSchemaContext()));
Assert.Throws<ArgumentNullException>("underlyingType", () => new XamlType(null, new XamlSchemaContext(), XamlTypeInvoker.UnknownInvoker));
}
[Fact]
public void Ctor_NullValueInTypeArguments_ThrowsArgumentException()
{
// TODO: paramName.
Assert.Throws<ArgumentException>(() => new XamlType("unknownTypeNamespace", "unknownTypeName", new XamlType?[] { null }, new XamlSchemaContext()));
Assert.Throws<ArgumentException>(() => new SubXamlType("typeName", new XamlType?[] { null }, new XamlSchemaContext()));
}
[Fact]
public void Ctor_NullSchemaContext_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("schemaContext", () => new XamlType("unknownTypeNamespace", "unknownTypeName", Array.Empty<XamlType>(), null));
Assert.Throws<ArgumentNullException>("schemaContext", () => new XamlType(typeof(int), null));
Assert.Throws<ArgumentNullException>("schemaContext", () => new XamlType(typeof(int), null, XamlTypeInvoker.UnknownInvoker));
Assert.Throws<ArgumentNullException>("schemaContext", () => new SubXamlType("typeName", Array.Empty<XamlType>(), null));
}
[Theory]
[InlineData("name", true)]
[InlineData("_aA1e\u0300\u0903", true)]
[InlineData("", false)]
[InlineData(" name ", false)]
[InlineData("1name", false)]
[InlineData("n#me", false)]
[InlineData("n.me", false)]
public void IsNameValid_Invoke_ReturnsExpected(string name, bool expected)
{
var type = new XamlType("namespace", name, null, new XamlSchemaContext());
Assert.Equal(expected, type.IsNameValid);
Assert.Equal(type.IsNameValid, type.IsNameValid);
}
[Fact]
public void PreferredXamlNamespace_Unknown_ReturnsExpected()
{
var type = new XamlType("namespace", "name", null, new XamlSchemaContext());
Assert.Equal("namespace", type.PreferredXamlNamespace);
}
[Fact]
public void PreferredXamlNamespace_UnderlyingType_ReturnsExpected()
{
var type = new XamlType(typeof(int), new XamlSchemaContext());
Assert.Equal("http://schemas.microsoft.com/winfx/2006/xaml", type.PreferredXamlNamespace);
}
[Fact]
public void PreferredXamlNamespace_GetXamlNamespacesReturnsNonEmpty_ReturnsFirstElement()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext()) { GetXamlNamespacesResult = new string[] { "namespace1", "namespace2" } };
Assert.Equal("namespace1", type.PreferredXamlNamespace);
}
[Fact]
public void PreferredXamlNamespace_GetXamlNamespacesReturnsEmpty_ReturnsNull()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext()) { GetXamlNamespacesResult = Array.Empty<string>() };
Assert.Null(type.PreferredXamlNamespace);
}
[Fact]
public void PreferredXamlNamespace_GetXamlNamespacesReturnsNull_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext()) { GetXamlNamespacesResult = null };
Assert.Throws<NullReferenceException>(() => type.PreferredXamlNamespace);
}
public static IEnumerable<object?[]> GetXamlNamespaces_TestData()
{
const string Default = "http://schemas.microsoft.com/winfx/2006/xaml";
static string Name(Assembly assembly) => new AssemblyName(assembly.FullName!).Name!;
// Unknown.
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), new string[] { "namespace" } };
yield return new object?[] { new SubXamlType("", "name", null, new XamlSchemaContext()), new string[] { "" } };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new string[] { "" } };
yield return new object?[] { new NoUnderlyingOrBaseType(), new string[] { "" } };
// Clr Type.
yield return new object?[]
{
new XamlType(typeof(int), new XamlSchemaContext()),
new string[] { Default, $"clr-namespace:System;assembly={Name(typeof(int).Assembly)}" }
};
yield return new object?[]
{
new XamlType(typeof(int), new XamlSchemaContext(new XamlSchemaContextSettings
{
FullyQualifyAssemblyNamesInClrNamespaces = true
})),
new string[] { Default, $"clr-namespace:System;assembly={typeof(int).Assembly.FullName}" }
};
// Custom type.
yield return new object?[]
{
new XamlType(typeof(GlobalNamespaceClass), new XamlSchemaContext()),
new string[] { $"clr-namespace:;assembly={Name(typeof(GlobalNamespaceClass).Assembly)}" }
};
yield return new object?[]
{
new XamlType(typeof(GlobalNamespaceClass), new XamlSchemaContext(new XamlSchemaContextSettings
{
FullyQualifyAssemblyNamesInClrNamespaces = true
})),
new string[] { $"clr-namespace:;assembly={typeof(GlobalNamespaceClass).Assembly.FullName}" }
};
yield return new object?[]
{
new XamlType(typeof(XamlTypeTests), new XamlSchemaContext()),
new string[] { $"clr-namespace:System.Xaml.Tests;assembly={Name(typeof(GlobalNamespaceClass).Assembly)}" }
};
yield return new object?[]
{
new XamlType(typeof(XamlTypeTests), new XamlSchemaContext(new XamlSchemaContextSettings
{
FullyQualifyAssemblyNamesInClrNamespaces = true
})),
new string[] { $"clr-namespace:System.Xaml.Tests;assembly={typeof(GlobalNamespaceClass).Assembly.FullName}" }
};
// Reflection Only Assembly.
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlTypeTests)), new XamlSchemaContext()),
new string[] { $"clr-namespace:System.Xaml.Tests;assembly={Name(typeof(XamlTypeTests).Assembly)}" }
};
yield return new object?[]
{
new XamlType(new CustomType(typeof(XamlTypeTests))
{
AssemblyResult = new CustomAssembly(typeof(XamlTypeTests).Assembly)
{
ReflectionOnlyResult = true,
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XmlnsDefinitionAttribute).GetConstructors()[0],
ConstructorArgumentsResult = new CustomAttributeTypedArgument[]
{
new CustomAttributeTypedArgument(typeof(string), "xmlNamespace"),
new CustomAttributeTypedArgument(typeof(string), "System.Xaml.Tests")
}
}
}
}
}, new XamlSchemaContext()),
new string[] { "xmlNamespace", $"clr-namespace:System.Xaml.Tests;assembly={Name(typeof(XamlTypeTests).Assembly)}" }
};
// Dynamic Assembly.
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("Name");
TypeBuilder dynamicType = dynamicModule.DefineType("Type");
Type createdDynamicType = dynamicType.CreateType();
var dynamicCacheContext = new XamlSchemaContext();
yield return new object?[]
{
new XamlType(createdDynamicType, dynamicCacheContext),
new string[] { $"clr-namespace:;assembly=Name" }
};
yield return new object?[]
{
new XamlType(createdDynamicType, dynamicCacheContext),
new string[] { $"clr-namespace:;assembly=Name" }
};
}
[Theory]
[MemberData(nameof(GetXamlNamespaces_TestData))]
public void GetXamlNamespaces_Type_ReturnsExpected(XamlType type, string[] expected)
{
Assert.Equal(expected, type.GetXamlNamespaces());
}
public static IEnumerable<object[]> GetXamlNamespaces_InvalidXmlnsDefinitionAttribute_TestData()
{
yield return new object[]
{
new CustomAttributeTypedArgument[]
{
new CustomAttributeTypedArgument(typeof(string), null),
new CustomAttributeTypedArgument(typeof(string), "clrNamespace")
}
};
yield return new object[]
{
new CustomAttributeTypedArgument[]
{
new CustomAttributeTypedArgument(typeof(string), ""),
new CustomAttributeTypedArgument(typeof(string), "clrNamespace")
}
};
yield return new object[]
{
new CustomAttributeTypedArgument[]
{
new CustomAttributeTypedArgument(typeof(string), "xmlNamespace"),
new CustomAttributeTypedArgument(typeof(string), null)
}
};
}
[Theory]
[MemberData(nameof(GetXamlNamespaces_InvalidXmlnsDefinitionAttribute_TestData))]
public void GetXamlNamespaces_InvalidXmlnsDefinitionAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new CustomXamlType(new CustomType(typeof(int))
{
AssemblyResult = new CustomAssembly(typeof(int).Assembly)
{
ReflectionOnlyResult = true,
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XmlnsDefinitionAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.GetXamlNamespaces());
}
[Fact]
public void GetXamlNamespaces_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(new CustomType(typeof(int))
{
AssemblyResult = new CustomAssembly(typeof(int).Assembly)
{
GetCustomAttributesMap = new Dictionary<Type, object?[]?>
{
{ typeof(XmlnsDefinitionAttribute), null }
}
}
}, new XamlSchemaContext());
Assert.Throws<NullReferenceException>(() => type.GetXamlNamespaces());
}
[Fact]
public void GetXamlNamespaces_InvalidAttributeResultType_ThrowsInvalidCastException()
{
var type = new CustomXamlType(new CustomType(typeof(int))
{
AssemblyResult = new CustomAssembly(typeof(int).Assembly)
{
GetCustomAttributesMap = new Dictionary<Type, object?[]?>
{
{ typeof(XmlnsDefinitionAttribute), new object[] { new XmlnsDefinitionAttribute("xmlNamespace", "clrNamespace") } }
}
}
}, new XamlSchemaContext());
Assert.Throws<InvalidCastException>(() => type.GetXamlNamespaces());
}
[Fact]
public void GetXamlNamespaces_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(new CustomType(typeof(int))
{
AssemblyResult = new CustomAssembly(typeof(int).Assembly)
{
GetCustomAttributesMap = new Dictionary<Type, object?[]?>
{
{ typeof(XmlnsDefinitionAttribute), new Attribute?[] { null } }
}
}
}, new XamlSchemaContext());
Assert.Throws<NullReferenceException>(() => type.GetXamlNamespaces());
}
[Fact]
public void GetXamlNamespaces_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(new CustomType(typeof(int))
{
AssemblyResult = new CustomAssembly(typeof(int).Assembly)
{
GetCustomAttributesMap = new Dictionary<Type, object?[]?>
{
{ typeof(XmlnsDefinitionAttribute), new Attribute[] { new AttributeUsageAttribute(AttributeTargets.All) } }
}
}
}, new XamlSchemaContext());
Assert.Throws<InvalidCastException>(() => type.GetXamlNamespaces());
}
public static IEnumerable<object?[]> LookupAliasedProperty_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), XamlLanguage.Key, null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), XamlLanguage.Key, null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), XamlLanguage.Key, null };
yield return new object?[] { new NoUnderlyingOrBaseType(), XamlLanguage.Key, null };
// Key.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new DictionaryKeyPropertyAttribute("name") }
}
},
XamlLanguage.Key,
new XamlMember("name", new XamlType(typeof(int), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Key,
new XamlMember("keyName", new XamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Key,
new XamlMember("keyName", new XamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullAttributes), new XamlSchemaContext()),
XamlLanguage.Key,
null
};
// Name.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new RuntimeNamePropertyAttribute("name") }
}
},
XamlLanguage.Name,
new XamlMember("name", new XamlType(typeof(int), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Name,
new XamlMember("runtimeName", new XamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Name,
new XamlMember("runtimeName", new XamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullAttributes), new XamlSchemaContext()),
XamlLanguage.Name,
null
};
// Uid.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new UidPropertyAttribute("name") }
}
},
XamlLanguage.Uid,
new XamlMember("name", new XamlType(typeof(int), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Uid,
new XamlMember("uidName", new XamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Uid,
new XamlMember("uidName", new XamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullAttributes), new XamlSchemaContext()),
XamlLanguage.Uid,
null
};
// Lang.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XmlLangPropertyAttribute("name") }
}
},
XamlLanguage.Lang,
new XamlMember("name", new XamlType(typeof(int), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Lang,
new XamlMember("langName", new XamlType(typeof(ClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()),
XamlLanguage.Lang,
new XamlMember("langName", new XamlType(typeof(InheritedClassWithAliasedAttributes), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullAttributes), new XamlSchemaContext()),
XamlLanguage.Lang,
null
};
// Other.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
XamlLanguage.Lang,
null
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XmlLangPropertyAttribute("name") }
}
},
new XamlDirective("namespace", "name"),
null
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(int)), new XamlSchemaContext()),
XamlLanguage.Lang,
null
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
XamlLanguage.Lang,
null
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
XamlLanguage.Lang,
null
};
}
[Theory]
[MemberData(nameof(LookupAliasedProperty_TestData))]
public void LookupAliasedProperty_Type_ReturnsExpected(SubXamlType type, XamlDirective directive, XamlMember expected)
{
Assert.Equal(expected, type.LookupAliasedPropertyEntry(directive));
XamlMember actual = type.GetAliasedProperty(directive);
Assert.Equal(expected, actual);
Assert.Same(actual, type.GetAliasedProperty(directive));
}
[Fact]
public void LookupAliasedProperty_NullDirective_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("key", () => type.LookupAliasedPropertyEntry(null!));
Assert.Throws<ArgumentNullException>("key", () => type.GetAliasedProperty(null));
}
public static IEnumerable<object[]> LookupAliasedProperty_Invalid_TestData()
{
yield return new object[] { XamlLanguage.Key };
yield return new object[] { XamlLanguage.Name };
yield return new object[] { XamlLanguage.Uid };
yield return new object[] { XamlLanguage.Lang };
}
[Theory]
[MemberData(nameof(LookupAliasedProperty_Invalid_TestData))]
public void LookupAliasedProperty_NullAttributeResult_ThrowsNullReferenceException(XamlDirective directive)
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupAliasedPropertyEntry(directive));
Assert.Throws<NullReferenceException>(() => type.GetAliasedProperty(directive));
}
[Theory]
[MemberData(nameof(LookupAliasedProperty_Invalid_TestData))]
public void LookupAliasedProperty_NullItemInAttributeResult_ThrowsNullReferenceException(XamlDirective directive)
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupAliasedPropertyEntry(directive));
Assert.Throws<NullReferenceException>(() => type.GetAliasedProperty(directive));
}
[Theory]
[MemberData(nameof(LookupAliasedProperty_Invalid_TestData))]
public void LookupAliasedProperty_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException(XamlDirective directive)
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupAliasedPropertyEntry(directive));
Assert.Throws<InvalidCastException>(() => type.GetAliasedProperty(directive));
}
public static IEnumerable<object[]> LookupAliasedProperty_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupAliasedProperty_InvalidAttribute_TestData))]
public void LookupAliasedProperty_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(int))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XmlLangPropertyAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupAliasedPropertyEntry(XamlLanguage.Lang));
Assert.Throws<XamlSchemaException>(() => type.GetAliasedProperty(XamlLanguage.Lang));
}
private class InheritedClassWithAliasedAttributes : ClassWithAliasedAttributes
{
}
[RuntimeNamePropertyAttribute("runtimeName")]
[DictionaryKeyPropertyAttribute("keyName")]
[UidPropertyAttribute("uidName")]
[XmlLangPropertyAttribute("langName")]
private class ClassWithAliasedAttributes
{
}
[RuntimeNamePropertyAttribute(null!)]
[DictionaryKeyPropertyAttribute(null!)]
[UidPropertyAttribute(null!)]
[XmlLangPropertyAttribute(null!)]
private class ClassWithNullAttributes
{
}
public static IEnumerable<object?[]> LookupAllAttachableMembers_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType(typeof(EmptyClass), new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddHandler)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("Event", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddEventHandler)), new XamlSchemaContext()),
new XamlMember("GetOnlyDictionaryProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyIntProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyIntProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyListProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyListProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyXDataProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyXDataProperty)), null, new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(AttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(AttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("SetOnlyProperty", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetSetOnlyProperty)), new XamlSchemaContext()),
},
new XamlMember[]
{
new XamlMember("", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddHandler)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("Event", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddEventHandler)), new XamlSchemaContext()),
new XamlMember("GetOnlyDictionaryProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyIntProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyIntProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyListProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyListProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyXDataProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyXDataProperty)), null, new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(AttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("SetOnlyProperty", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetSetOnlyProperty)), new XamlSchemaContext())
}
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateAttachableMembersDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddHandler)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("Event", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddEventHandler)), new XamlSchemaContext()),
new XamlMember("GetOnlyDictionaryProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyIntProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyIntProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyListProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyListProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyXDataProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyXDataProperty)), null, new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(PrivateAttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(PrivateAttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("SetOnlyProperty", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetSetOnlyProperty)), new XamlSchemaContext()),
},
new XamlMember[]
{
new XamlMember("", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddHandler)), new XamlSchemaContext()),
new XamlMember("DifferentFirstParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext()),
new XamlMember("DifferentSecondParameter", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext()),
new XamlMember("Event", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddEventHandler)), new XamlSchemaContext()),
new XamlMember("GetOnlyDictionaryProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyIntProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyIntProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyListProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyListProperty)), null, new XamlSchemaContext()),
new XamlMember("GetOnlyXDataProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyXDataProperty)), null, new XamlSchemaContext()),
new XamlMember("GetSetProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext()),
new XamlMember("InternalProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ProtectedProperty", typeof(PrivateAttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("SetOnlyProperty", null, typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetSetOnlyProperty)), new XamlSchemaContext())
}
};
yield return new object?[]
{
new SubXamlType(typeof(DuplicateDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("Event", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddEventHandler), new Type[] { typeof(object), typeof(EventHandler) }), new XamlSchemaContext()),
new XamlMember("Getter", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetGetter), new Type[] { typeof(string) }), null, new XamlSchemaContext()),
new XamlMember("InternalThenInternal", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetInternalThenInternal), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null), null, new XamlSchemaContext()),
new XamlMember("InternalThenInternalEvent", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddInternalThenInternalEventHandler), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(object), typeof(EventHandler) }, null), new XamlSchemaContext()),
new XamlMember("InternalThenPublic", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetInternalThenPublic), new Type[] { typeof(int) }), null, new XamlSchemaContext()),
new XamlMember("InternalThenPublicEvent", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddInternalThenPublicEventHandler), new Type[] { typeof(object), typeof(OtherHandler) }), new XamlSchemaContext()),
new XamlMember("PublicThenInternal", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetPublicThenInternal), new Type[] { typeof(string) }), null, new XamlSchemaContext()),
new XamlMember("PublicThenInternalEvent", typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddPublicThenInternalEventHandler), new Type[] { typeof(object), typeof(EventHandler) }), new XamlSchemaContext()),
new XamlMember("Setter", null, typeof(DuplicateDataClass).GetMethod(nameof(DuplicateDataClass.SetSetter), new Type[] { typeof(string), typeof(int) }), new XamlSchemaContext()),
}
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateDuplicateDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("Event", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddEventHandler), new Type[] { typeof(object), typeof(EventHandler) }), new XamlSchemaContext()),
new XamlMember("Getter", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetGetter), new Type[] { typeof(string) }), null, new XamlSchemaContext()),
new XamlMember("InternalThenInternal", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetInternalThenInternal), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null), null, new XamlSchemaContext()),
new XamlMember("InternalThenInternalEvent", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddInternalThenInternalEventHandler), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(object), typeof(EventHandler) }, null), new XamlSchemaContext()),
new XamlMember("InternalThenPublic", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetInternalThenPublic), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string) }, null), null, new XamlSchemaContext()),
new XamlMember("InternalThenPublicEvent", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddInternalThenPublicEventHandler), BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(object), typeof(EventHandler) }, null), new XamlSchemaContext()),
new XamlMember("PublicThenInternal", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.GetPublicThenInternal), new Type[] { typeof(string) }), null, new XamlSchemaContext()),
new XamlMember("PublicThenInternalEvent", typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.AddPublicThenInternalEventHandler), new Type[] { typeof(object), typeof(EventHandler) }), new XamlSchemaContext()),
new XamlMember("Setter", null, typeof(PrivateDuplicateDataClass).GetMethod(nameof(DuplicateDataClass.SetSetter), new Type[] { typeof(string), typeof(int) }), new XamlSchemaContext()),
}
};
yield return new object?[]
{
new SubXamlType(typeof(NonMatchingInternalSetterClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("DictionaryProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("DictionaryProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("ListProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetListProperty)), null, new XamlSchemaContext()),
new XamlMember("ListProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetListProperty)), null, new XamlSchemaContext()),
new XamlMember("XDataProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetXDataProperty)), null, new XamlSchemaContext()),
new XamlMember("XDataProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetXDataProperty)), null, new XamlSchemaContext())
},
new XamlMember[]
{
new XamlMember("DictionaryProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetDictionaryProperty)), null, new XamlSchemaContext()),
new XamlMember("ListProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetListProperty)), null, new XamlSchemaContext()),
new XamlMember("XDataProperty", typeof(NonMatchingInternalSetterClass).GetMethod(nameof(NonMatchingInternalSetterClass.GetXDataProperty)), null, new XamlSchemaContext())
}
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateNonMatchingInternalSetterClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("DictionaryProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("DictionaryProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
},
new XamlMember[]
{
new XamlMember("DictionaryProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(PrivateNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
}
};
yield return new object?[]
{
new SubXamlType(typeof(InternalGetterNonMatchingInternalSetterClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember("DictionaryProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("DictionaryProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
},
new XamlMember[]
{
new XamlMember("DictionaryProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetDictionaryProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("IntProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetIntProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("ListProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetListProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember("XDataProperty", null, typeof(InternalGetterNonMatchingInternalSetterClass).GetMethod(nameof(PrivateNonMatchingInternalSetterClass.SetXDataProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
}
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupAllAttachableMembersResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupAllAttachableMembers_TestData))]
public void LookupAllAttachableMembers_Invoke_ReturnsExpected(SubXamlType type, XamlMember[]? expectedLookup, XamlMember[]? expectedGet = null)
{
AssertEqualXamlMembers(expectedGet ?? expectedLookup ?? Array.Empty<XamlMember>(), type.GetAllAttachableMembers());
AssertEqualXamlMembers(expectedLookup, type.LookupAllAttachableMembersEntry());
}
#if !DEBUG // This triggers a Debug.Assert.
[Fact]
public void LookupAllAttachableMembers_MembersNotCalled_ThrowsNullReferenceException()
{
var type = new SubXamlType(typeof(string), new XamlSchemaContext());
Assert.Throws<NullReferenceException>(() => type.LookupAllAttachableMembersEntry());
}
#endif
private static MethodInfo GetUnderlyingGetter(XamlMember member)
{
MethodInfo underlyingGetter = member.GetType().GetMethod("LookupUnderlyingGetter", BindingFlags.Instance | BindingFlags.NonPublic)!;
return (MethodInfo)underlyingGetter.Invoke(member, Array.Empty<object>())!;
}
private static MethodInfo GetUnderlyingSetter(XamlMember member)
{
MethodInfo underlyingSetter = member.GetType().GetMethod("LookupUnderlyingSetter", BindingFlags.Instance | BindingFlags.NonPublic)!;
return (MethodInfo)underlyingSetter.Invoke(member, Array.Empty<object>())!;
}
#pragma warning disable IDE0060, IDE0051, CA1052 // Remove unused parameter, Remove unused member, Static holder types should be Static or NotInheritable
public class AttachableMembersDataClass
{
public static int GetGetSetProperty(string value) => 0;
public static void SetGetSetProperty(string value1, int value2) { }
public static int GetDifferentFirstParameter(string value) => 0;
public static void SetDifferentFirstParameter(int value1, int value2) { }
public static int GetDifferentSecondParameter(string value) => 0;
public static void SetDifferentSecondParameter(string value1, string value2) { }
protected static int GetProtectedProperty(string value) => 0;
protected static void SetProtectedProperty(string value1, int value2) { }
internal static int GetInternalProperty(string value) => 0;
internal static void SetInternalProperty(string value1, int value2) { }
private static int GetPrivateProperty(string value) => 0;
private static void SetPrivateProperty(string value1, int value2) { }
public static int GetGetOnlyIntProperty(int value) => 0;
public static List<int>? GetGetOnlyListProperty(int value) => null;
public static Dictionary<int, string>? GetGetOnlyDictionaryProperty(int value) => null;
public static IXmlSerializable? GetGetOnlyXDataProperty(int value) => null;
public static void SetSetOnlyProperty(int value1, int value2) { }
public static void GetVoid(string value) { }
public static int GetParameterless() => 0;
public static int GetTooManyParameters(string value1, int value2) => 0;
public static void SetParameterless() { }
public static void SetTooManyParameters() { }
public static void AddEventHandler(object value, EventHandler handler) { }
private static void AddPrivateEventHandler(object value, EventHandler handler) { }
public static void AddHandler(object value, EventHandler handler) { }
public static void AddParameterlessHandler() { }
public static void AddTooManyParametersHandler(object value1, EventHandler handler, int value2) { }
public static void AddInvalidSecondParameterHandler(object value1, object value2) { }
public static void AddDoesNotEndCorrectly() { }
public static void DoesNotStartWithGetSetAdd() { }
}
private class PrivateAttachableMembersDataClass
{
public static int GetGetSetProperty(string value) => 0;
public static void SetGetSetProperty(string value1, int value2) { }
public static int GetDifferentFirstParameter(string value) => 0;
public static void SetDifferentFirstParameter(int value1, int value2) { }
public static int GetDifferentSecondParameter(string value) => 0;
public static void SetDifferentSecondParameter(string value1, string value2) { }
protected static int GetProtectedProperty(string value) => 0;
protected static void SetProtectedProperty(string value1, int value2) { }
internal static int GetInternalProperty(string value) => 0;
internal static void SetInternalProperty(string value1, int value2) { }
private static int GetPrivateProperty(string value) => 0;
private static void SetPrivateProperty(string value1, int value2) { }
public static int GetGetOnlyIntProperty(int value) => 0;
public static List<int>? GetGetOnlyListProperty(int value) => null;
public static Dictionary<int, string>? GetGetOnlyDictionaryProperty(int value) => null;
public static IXmlSerializable? GetGetOnlyXDataProperty(int value) => null;
public static void SetSetOnlyProperty(int value1, int value2) { }
public static void GetVoid(string value) { }
public static int GetParameterless() => 0;
public static int GetTooManyParameters(string value1, int value2) => 0;
public static void SetParameterless() { }
public static void SetTooManyParameters() { }
public static void AddEventHandler(object value, EventHandler handler) { }
private static void AddPrivateEventHandler(object value, EventHandler handler) { }
public static void AddHandler(object value, EventHandler handler) { }
public static void AddParameterlessHandler() { }
public static void AddTooManyParametersHandler(object value1, EventHandler handler, int value2) { }
public static void AddInvalidSecondParameterHandler(object value1, object value2) { }
public static void AddDoesNotEndCorrectly() { }
public static void DoesNotStartWithGetSetAdd() { }
}
public class DuplicateDataClass
{
public static int GetGetter(string value) => 0;
public static int GetGetter(int value) => 0;
public static int SetSetter(string value1, int value2) => 0;
public static int SetSetter(int value1, int value2) => 0;
public static int GetPublicThenInternal(string value) => 0;
internal static int GetPublicThenInternal(int value) => 0;
internal static int GetInternalThenPublic(string value) => 0;
public static int GetInternalThenPublic(int value) => 0;
internal static int GetInternalThenInternal(string value) => 0;
internal static int GetInternalThenInternal(int value) => 0;
public static void AddEventHandler(object value, EventHandler handler) { }
public static void AddEventHandler(object value, OtherHandler handler) { }
public static int AddPublicThenInternalEventHandler(object value, EventHandler handler) => 0;
internal static int AddPublicThenInternalEventHandler(object value, OtherHandler handler) => 0;
internal static int AddInternalThenPublicEventHandler(object value, EventHandler handler) => 0;
public static int AddInternalThenPublicEventHandler(object value, OtherHandler handler) => 0;
internal static int AddInternalThenInternalEventHandler(object value, EventHandler handler) => 0;
internal static int AddInternalThenInternalEventHandler(object value, OtherHandler handler) => 0;
}
private class PrivateDuplicateDataClass
{
public static int GetGetter(string value) => 0;
public static int GetGetter(int value) => 0;
public static int SetSetter(string value1, int value2) => 0;
public static int SetSetter(int value1, int value2) => 0;
public static int GetPublicThenInternal(string value) => 0;
internal static int GetPublicThenInternal(int value) => 0;
internal static int GetInternalThenPublic(string value) => 0;
public static int GetInternalThenPublic(int value) => 0;
internal static int GetInternalThenInternal(string value) => 0;
internal static int GetInternalThenInternal(int value) => 0;
public static void AddEventHandler(object value, EventHandler handler) { }
public static void AddEventHandler(object value, OtherHandler handler) { }
public static int AddPublicThenInternalEventHandler(object value, EventHandler handler) => 0;
internal static int AddPublicThenInternalEventHandler(object value, OtherHandler handler) => 0;
internal static int AddInternalThenPublicEventHandler(object value, EventHandler handler) => 0;
public static int AddInternalThenPublicEventHandler(object value, OtherHandler handler) => 0;
internal static int AddInternalThenInternalEventHandler(object value, EventHandler handler) => 0;
internal static int AddInternalThenInternalEventHandler(object value, OtherHandler handler) => 0;
}
public class NonMatchingInternalSetterClass
{
public static int GetIntProperty(string value1) => 0;
internal static int SetIntProperty(string value1, string value2) => 0;
public static List<int>? GetListProperty(string value1) => null;
internal static int SetListProperty(string value1, string value2) => 0;
public static Dictionary<int, string>? GetDictionaryProperty(string value1) => null;
internal static int SetDictionaryProperty(string value1, string value2) => 0;
public static IXmlSerializable? GetXDataProperty(string value1) => null;
internal static int SetXDataProperty(string value1, string value2) => 0;
}
public class InternalGetterNonMatchingInternalSetterClass
{
internal static int GetIntProperty(string value1) => 0;
internal static int SetIntProperty(string value1, string value2) => 0;
internal static List<int>? GetListProperty(string value1) => null;
internal static int SetListProperty(string value1, string value2) => 0;
internal static Dictionary<int, string>? GetDictionaryProperty(string value1) => null;
internal static int SetDictionaryProperty(string value1, string value2) => 0;
internal static IXmlSerializable? GetXDataProperty(string value1) => null;
internal static int SetXDataProperty(string value1, string value2) => 0;
}
private class PrivateNonMatchingInternalSetterClass
{
public static int GetIntProperty(string value1) => 0;
internal static int SetIntProperty(string value1, string value2) => 0;
public static List<int>? GetListProperty(string value1) => null;
internal static int SetListProperty(string value1, string value2) => 0;
public static Dictionary<int, string>? GetDictionaryProperty(string value1) => null;
internal static int SetDictionaryProperty(string value1, string value2) => 0;
public static IXmlSerializable? GetXDataProperty(string value1) => null;
internal static int SetXDataProperty(string value1, string value2) => 0;
}
private class EmptyClass
{
}
#pragma warning restore IDE0060, IDE0051, CA1052 // Remove unused parameter, Remove unused member, Static holder types should be Static or NotInheritable
public static IEnumerable<object?[]> LookupAllMembers_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), Array.Empty<XamlMember>() };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.Property)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.SetOnlyProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateGetProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateSetProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyListProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyDictionaryProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetXDataProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.InternalProperty), BindingFlags.Instance | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty("ProtectedProperty", BindingFlags.Instance | BindingFlags.NonPublic), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetEvent(nameof(MembersDataClass.Event)), new XamlSchemaContext())
}
};
yield return new object?[]
{
new SubXamlType(typeof(MoreDerivedShadowedDataClass), new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext())
},
new XamlMember[]
{
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext())
},
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateMembersDataClass), new XamlSchemaContext()),
Array.Empty<XamlMember>()
};
yield return new object?[]
{
new SubXamlType(new CustomType(typeof(MembersDataClass))
{
GetPropertiesResult = new PropertyInfo[]
{
typeof(ShadowedBaseClass).GetProperty(nameof(ShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!
},
GetEventsResult = new EventInfo[]
{
typeof(ShadowedBaseClass).GetEvent(nameof(ShadowedBaseClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!
}
}, new XamlSchemaContext()),
new XamlMember[]
{
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext())
},
new XamlMember[]
{
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetEvent(nameof(MoreDerivedShadowedDataClass.Event), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext())
}
};
yield return new object?[]
{
new CustomXamlType(typeof(MembersDataClass), new XamlSchemaContext())
{
LookupAllMembersResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupAllMembers_TestData))]
public void LookupAllMembers_Invoke_ReturnsExpected(SubXamlType type, XamlMember[]? expectedLookup, XamlMember[]? expectedGet = null)
{
IEnumerable<XamlMember> expectedGetAllMembers = expectedGet ?? expectedLookup ?? Array.Empty<XamlMember>();
Assert.Equal(expectedGetAllMembers.OrderBy(m => m.Name), type.GetAllMembers().OrderBy(m => m.Name));
Assert.Equal(expectedLookup?.OrderBy(m => m.Name), type.LookupAllMembersEntry()?.OrderBy(m => m.Name));
}
#if !DEBUG // This triggers a Debug.Assert.
[Fact]
public void LookupAllMembers_MembersNotCalled_ThrowsNullReferenceException()
{
var type = new SubXamlType(typeof(string), new XamlSchemaContext());
Assert.Throws<NullReferenceException>(() => type.LookupAllMembersEntry());
}
#endif
#pragma warning disable IDE0060, IDE0051 // Remove unused parameter, Remove unused member
public class MembersDataClass
{
public int Property { get; set; }
public int GetOnlyProperty { get; }
public List<int>? GetOnlyListProperty { get; }
public Dictionary<int, string>? GetOnlyDictionaryProperty { get; }
public IXmlSerializable? GetXDataProperty { get; }
public int SetOnlyProperty { set { } }
public int PrivateGetProperty { private get; set; }
public int PrivateSetProperty { get; private set; }
public int this[int i]
{
get => 0;
set { }
}
internal int InternalProperty { get; set; }
protected int ProtectedProperty { get; set; }
private int PrivateProperty { get; set; }
public static int StaticProperty { get; set; }
public event EventHandler Event
{
add { }
remove { }
}
private event EventHandler PrivateEvent
{
add { }
remove { }
}
public static event EventHandler StaticEvent
{
add { }
remove { }
}
}
public class ShadowedBaseClass
{
public Array? Property { get; set; }
public int AccessChangedProperty { get; set; }
public event EventHandler Event
{
add { }
remove { }
}
public event EventHandler AccessChangedEvent
{
add { }
remove { }
}
}
public class MoreDerivedShadowedDataClass : ShadowedBaseClass
{
public new int[]? Property { get; set; }
private new int AccessChangedProperty { get; set; }
public new event OtherHandler Event
{
add { }
remove { }
}
private new event EventHandler AccessChangedEvent
{
add { }
remove { }
}
}
public class EvenMoreDerivedShadowedBaseClass : MoreDerivedShadowedDataClass
{
public new string[]? Property { get; set; }
}
public class PrivateMembersDataClass
{
private int PrivateProperty { get; set; }
private EventHandler? PrivateEvent { get; set; }
}
public delegate void OtherHandler();
#pragma warning restore IDE0060, IDE0051 // Remove unused parameter, Remove unused member
public static IEnumerable<object?[]> LookupAllowedContentTypes_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType?[] { null } };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new XamlType?[] { null } };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), new XamlType?[] { null } };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), new XamlType?[] { null } };
yield return new object?[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
yield return new object?[] { new NoUnderlyingOrBaseType(), new XamlType?[] { null } };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(List<string>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentWrapperAttribute(typeof(ClassWithUnknownContentPropertyAttribute)) }
}
},
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new CustomXamlType(typeof(List<string>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentWrapperAttribute(typeof(int)) }
}
},
new XamlType?[] { null }
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithContentPropertyContentWrapperAttribute), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithContentWrapperAttribute), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithContentWrapperAttribute), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithContentWrapperAttribute)), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(List<string>)), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithContentWrapperAttribute), new XamlSchemaContext())
{
LookupAllowedContentTypesResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupAllowedContentTypes_TestData))]
public void LookupAllowedContentTypes_Invoke_ReturnsExpected(SubXamlType type, IList<XamlType> expected)
{
Assert.Equal(expected, type.LookupAllowedContentTypesEntry());
Assert.Equal((type.IsCollection || type.IsDictionary) ? expected ?? Array.Empty<XamlType>() : null, type.AllowedContentTypes);
}
[Fact]
public void LookupAllowedContentTypes_NullTypeInAttribute_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(ClassWithNullContentWrapperAttribute), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("type", () => type.LookupAllowedContentTypesEntry());
Assert.Throws<ArgumentNullException>("type", () => type.AllowedContentTypes);
}
[Fact]
public void LookupAllowedContentTypes_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupAllowedContentTypesEntry());
Assert.Throws<NullReferenceException>(() => type.AllowedContentTypes);
}
[Fact]
public void LookupAllowedContentTypes_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupAllowedContentTypesEntry());
Assert.Throws<NullReferenceException>(() => type.AllowedContentTypes);
}
[Fact]
public void LookupAllowedContentTypes_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupAllowedContentTypesEntry());
Assert.Throws<InvalidCastException>(() => type.AllowedContentTypes);
}
[ContentWrapper(typeof(int))]
[ContentWrapper(typeof(ClassWithUnknownContentPropertyAttribute))]
[ContentWrapper(typeof(ClassWithKnownContentPropertyAttribute))]
[ContentWrapper(typeof(ClassWithKnownContentPropertyAttribute))]
[ContentWrapper(typeof(InheritedClassWithContentPropertyAttribute))]
private class ClassWithContentPropertyContentWrapperAttribute : Collection<string>
{
}
public static IEnumerable<object[]> LookupAllowedContentTypes_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupAllowedContentTypes_InvalidAttribute_TestData))]
public void LookupAllowedContentTypes_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(List<int>))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(ContentWrapperAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupAllowedContentTypesEntry());
Assert.Throws<XamlSchemaException>(() => type.AllowedContentTypes);
}
public static IEnumerable<object?[]> LookupAttachableMember_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), "name", null };
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), "", null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), "name", null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), "name", null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), "name", null };
yield return new object?[] { new NoUnderlyingOrBaseType(), "name", null };
// Property.
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"GetSetProperty",
new XamlMember("GetSetProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetSetProperty)), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"ProtectedProperty",
new XamlMember("ProtectedProperty", typeof(AttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"InternalProperty",
new XamlMember("InternalProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"PrivateProperty",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"GetOnlyIntProperty",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"GetOnlyListProperty",
new XamlMember("GetOnlyListProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyListProperty)), null, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"GetOnlyDictionaryProperty",
new XamlMember("GetOnlyDictionaryProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyDictionaryProperty)), null, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"GetOnlyXDataProperty",
new XamlMember("GetOnlyXDataProperty", typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.GetGetOnlyXDataProperty)), null, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"DifferentFirstParameter",
new XamlMember("DifferentFirstParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentFirstParameter)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"DifferentSecondParameter",
new XamlMember("DifferentSecondParameter", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.SetDifferentSecondParameter)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"Void",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"Parameterless",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"TooManyParameters",
null
};
// Property in public class.
yield return new object?[]
{
new SubXamlType(typeof(PrivateAttachableMembersDataClass), new XamlSchemaContext()),
"GetSetProperty",
new XamlMember("GetSetProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(PrivateAttachableMembersDataClass.GetGetSetProperty)), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(PrivateAttachableMembersDataClass.SetGetSetProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateAttachableMembersDataClass), new XamlSchemaContext()),
"ProtectedProperty",
new XamlMember("ProtectedProperty", typeof(PrivateAttachableMembersDataClass).GetMethod("GetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod("SetProtectedProperty", BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateAttachableMembersDataClass), new XamlSchemaContext()),
"InternalProperty",
new XamlMember("InternalProperty", typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(PrivateAttachableMembersDataClass.GetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), typeof(PrivateAttachableMembersDataClass).GetMethod(nameof(PrivateAttachableMembersDataClass.SetInternalProperty), BindingFlags.Static | BindingFlags.NonPublic), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(PrivateAttachableMembersDataClass), new XamlSchemaContext()),
"PrivateProperty",
null
};
// Event.
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"Event",
new XamlMember("Event", null, typeof(AttachableMembersDataClass).GetMethod(nameof(AttachableMembersDataClass.AddEventHandler)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"PrivateEvent",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"Parameterless",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"TooManyParameters",
null
};
yield return new object?[]
{
new SubXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext()),
"InvalidSecondParameter",
null
};
yield return new object?[]
{
new CustomXamlType(typeof(AttachableMembersDataClass), new XamlSchemaContext())
{
LookupAttachableMemberResult = null
},
"name",
null
};
}
[Theory]
[MemberData(nameof(LookupAttachableMember_TestData))]
public void LookupAttachableMember_Invoke_ReturnsExpected(SubXamlType type, string name, XamlMember expectedLookup, XamlMember? expectedGet = null)
{
AssertEqualXamlMember(expectedLookup, type.LookupAttachableMemberEntry(name));
AssertEqualXamlMember(expectedGet ?? expectedLookup, type.GetAttachableMember(name));
}
[Fact]
public void LookupAttachableMember_NullName_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.Null(type.LookupAttachableMemberEntry(null!));
Assert.Throws<ArgumentNullException>("key", () => type.GetAttachableMember(null));
}
[Fact]
public void LookupAttachableMember_NullNameUnknownNoBaseType_ThrowsArgumentNullExceptionOnGetter()
{
var type = new NoUnderlyingOrBaseType();
Assert.Null(type.LookupAttachableMemberEntry(null!));
Assert.Throws<ArgumentNullException>("key", () => type.GetAttachableMember(null));
}
public static IEnumerable<object?[]> LookupBaseType_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), XamlLanguage.Object };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), XamlLanguage.Object };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(ValueType), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(IConvertible), new XamlSchemaContext()), null };
yield return new object?[]
{
new SubXamlType(typeof(CustomXamlSchemaContext), new CustomXamlSchemaContext
{
GetXamlTypeAction = type =>
{
Assert.Equal(typeof(XamlSchemaContext), type);
return XamlLanguage.Single;
}
}),
XamlLanguage.Single
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupBaseType_TestData))]
public void LookupBaseType_Invoke_ReturnsExpected(SubXamlType type, XamlType expected)
{
Assert.Equal(expected, type.LookupBaseTypeEntry());
Assert.Equal(expected, type.BaseType);
}
public static IEnumerable<object?[]> LookupCollectionKind_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new NoUnderlyingOrBaseType(), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(int[]), new XamlSchemaContext()), XamlCollectionKind.Array };
yield return new object?[] { new SubXamlType(typeof(IEnumerable), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(IEnumerable<int>), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(ICollection), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(ICollection<int>), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(IList), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(IList<int>), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(IDictionary), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(IDictionary<int, int>), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(Collection<int>), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(GetEnumeratorClass), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(InvalidReturnGetEnumeratorClass), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(InvalidParametersGetEnumeratorClass), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(MultiICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(ICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(InternalICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(MoreThanOneICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.Collection };
yield return new object?[] { new SubXamlType(typeof(PrivateICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(ProtectedICollectionImplementer), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(Dictionary<int, int>), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(IDictionaryImplementer), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(InternalIDictionaryImplementer), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(MoreThanOneIDictionaryImplementer), new XamlSchemaContext()), XamlCollectionKind.Dictionary };
yield return new object?[] { new SubXamlType(typeof(PrivateIDictionaryImplementer), new XamlSchemaContext()), XamlCollectionKind.None };
yield return new object?[] { new SubXamlType(typeof(ProtectedIDictionaryImplementer), new XamlSchemaContext()), XamlCollectionKind.None };
/*
yield return new object?[]
{
new CustomXamlType(typeof(ICollectionImplementer))
}
*/
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCollectionKindResult = (XamlCollectionKind)(XamlCollectionKind.Array + 1)
},
(XamlCollectionKind)(XamlCollectionKind.Array + 1)
};
}
[Theory]
[MemberData(nameof(LookupCollectionKind_TestData))]
public void LookupCollectionKind_Invoke_ReturnsExpected(SubXamlType type, XamlCollectionKind expected)
{
Assert.Equal(expected, type.LookupCollectionKindEntry());
Assert.Equal(expected == XamlCollectionKind.Array, type.IsArray);
Assert.Equal(expected == XamlCollectionKind.Collection, type.IsCollection);
Assert.Equal(expected == XamlCollectionKind.Dictionary, type.IsDictionary);
}
#pragma warning disable IDE0060, IDE0051 // Remove unused parameter, Remove unused member
private class GetEnumeratorClass
{
public IEnumerator GetEnumerator() => throw new NotImplementedException();
public void Add(object value) => throw new NotImplementedException();
}
private class InvalidReturnGetEnumeratorClass
{
public int GetEnumerator() => throw new NotImplementedException();
public void Add(object value) => throw new NotImplementedException();
}
private class InvalidParametersGetEnumeratorClass
{
public IEnumerator GetEnumerator(int value) => throw new NotImplementedException();
public void Add(object value) => throw new NotImplementedException();
}
private class MultiICollectionImplementer : ICollection<int>, ICollection<object>
{
public int Count => throw new NotImplementedException();
public bool IsReadOnly => throw new NotImplementedException();
public void Add(int item) => throw new NotImplementedException();
public void Add(object item) => throw new NotImplementedException();
public void Clear() => throw new NotImplementedException();
public bool Contains(int item) => throw new NotImplementedException();
public bool Contains(object item) => throw new NotImplementedException();
public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
public void CopyTo(object[] array, int arrayIndex) => throw new NotImplementedException();
IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
IEnumerator<object> IEnumerable<object>.GetEnumerator() => throw new NotImplementedException();
public bool Remove(int item) => throw new NotImplementedException();
public bool Remove(object item) => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
}
private class ICollectionImplementer : IEnumerable
{
public void Add(object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class MoreThanOneICollectionImplementer : ICollectionImplementer
{
public void Add(int value) => throw new NotImplementedException();
}
private class InternalICollectionImplementer : IEnumerable
{
internal void Add(object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class PrivateICollectionImplementer : IEnumerable
{
private void Add(object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class ProtectedICollectionImplementer : IEnumerable
{
protected void Add(object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class IDictionaryImplementer : IEnumerable
{
public void Add(object key, object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class MoreThanOneIDictionaryImplementer : IDictionaryImplementer
{
public void Add(int key, int value) => throw new NotImplementedException();
public void Add() => throw new NotImplementedException();
}
private class InternalIDictionaryImplementer : IEnumerable
{
internal void Add(object key, object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class PrivateIDictionaryImplementer : IEnumerable
{
private void Add(object key, object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class ProtectedIDictionaryImplementer : IEnumerable
{
protected void Add(object key, object value) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
#pragma warning restore IDE0060, IDE0051 // Remove unused parameter, Remove unused member
public static IEnumerable<object[]> LookupConstructionRequiresArguments_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(ClassWithDefaultConstructor), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(AbstractClass), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(IConvertible), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(NestedClass), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(ClassWithInternalDefaultConstructor), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(ClassWithProtectedDefaultConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ClassWithPrivateDefaultConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ClassWithCustomConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(StaticClass), new XamlSchemaContext()), true };
yield return new object[]
{
new CustomXamlType(typeof(ClassWithCustomConstructor), new XamlSchemaContext())
{
LookupConstructionRequiresArgumentsResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupConstructionRequiresArguments_TestData))]
public void LookupConstructionRequiresArguments_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupConstructionRequiresArgumentsEntry());
Assert.Equal(expected, type.ConstructionRequiresArguments);
}
public static IEnumerable<object?[]> LookupContentProperty_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentPropertyAttribute("name") }
}
},
new XamlMember("name", new XamlType(typeof(int), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentPropertyAttribute("name") }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithKnownContentPropertyAttribute), new XamlSchemaContext()),
new XamlMember(typeof(ClassWithKnownContentPropertyAttribute).GetProperty(nameof(ClassWithKnownContentPropertyAttribute.Name)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithUnknownContentPropertyAttribute), new XamlSchemaContext()),
new XamlMember("name", new XamlType(typeof(ClassWithUnknownContentPropertyAttribute), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithContentPropertyAttribute), new XamlSchemaContext()),
new XamlMember(typeof(ClassWithKnownContentPropertyAttribute).GetProperty(nameof(ClassWithKnownContentPropertyAttribute.Name)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullContentPropertyAttribute), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithDefaultContentPropertyAttribute), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithUnknownContentPropertyAttribute)), new XamlSchemaContext()),
new XamlMember("name", new XamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithUnknownContentPropertyAttribute)), new XamlSchemaContext()), false)
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithUnknownContentPropertyAttribute), new XamlSchemaContext())
{
LookupContentPropertyResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupContentProperty_TestData))]
public void LookupContentProperty_Invoke_ReturnsExpected(SubXamlType type, XamlMember expected)
{
Assert.Equal(expected, type.LookupContentPropertyEntry());
Assert.Equal(expected, type.ContentProperty);
}
[Fact]
public void LookupContentProperty_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupContentPropertyEntry());
Assert.Throws<NullReferenceException>(() => type.ContentProperty);
}
[Fact]
public void LookupContentProperty_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupContentPropertyEntry());
Assert.Throws<NullReferenceException>(() => type.ContentProperty);
}
[Fact]
public void LookupContentProperty_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupContentPropertyEntry());
Assert.Throws<InvalidCastException>(() => type.ContentProperty);
}
public static IEnumerable<object[]> LookupContentProperty_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupContentProperty_InvalidAttribute_TestData))]
public void LookupContentProperty_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(int))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(ContentPropertyAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupContentPropertyEntry());
Assert.Throws<XamlSchemaException>(() => type.ContentProperty);
}
[ContentProperty("name")]
private class ClassWithUnknownContentPropertyAttribute
{
}
[ContentProperty("Name")]
private class ClassWithKnownContentPropertyAttribute
{
public int Name { get; set; }
}
private class InheritedClassWithContentPropertyAttribute : ClassWithKnownContentPropertyAttribute
{
}
[ContentProperty(null)]
private class ClassWithNullContentPropertyAttribute
{
}
[ContentProperty]
private class ClassWithDefaultContentPropertyAttribute
{
}
public static IEnumerable<object?[]> LookupContentWrappers_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(List<string>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentWrapperAttribute(typeof(int)) }
}
},
new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }
};
yield return new object?[]
{
new CustomXamlType(typeof(List<string>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ContentWrapperAttribute(typeof(int)) }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithContentWrapperAttribute), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithContentWrapperAttribute), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithContentWrapperAttribute)), new XamlSchemaContext()),
new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(List<string>)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithContentWrapperAttribute), new XamlSchemaContext())
{
LookupContentWrappersResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupContentWrappers_TestData))]
public void LookupContentWrappers_Invoke_ReturnsExpected(SubXamlType type, IList<XamlType> expected)
{
Assert.Equal(expected, type.LookupContentWrappersEntry());
Assert.Equal(type.IsCollection ? expected ?? Array.Empty<XamlType>() : expected, type.ContentWrappers);
}
[Fact]
public void LookupContentWrappers_NullTypeInAttribute_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(ClassWithNullContentWrapperAttribute), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("type", () => type.LookupContentWrappersEntry());
Assert.Throws<ArgumentNullException>("type", () => type.ContentWrappers);
}
[Fact]
public void LookupContentWrappers_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupContentWrappersEntry());
Assert.Throws<NullReferenceException>(() => type.ContentWrappers);
}
[Fact]
public void LookupContentWrappers_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupContentWrappersEntry());
Assert.Throws<NullReferenceException>(() => type.ContentWrappers);
}
[Fact]
public void LookupContentWrappers_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupContentWrappersEntry());
Assert.Throws<InvalidCastException>(() => type.ContentWrappers);
}
public static IEnumerable<object[]> LookupContentWrappers_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupContentWrappers_InvalidAttribute_TestData))]
public void LookupContentWrappers_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(List<int>))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(ContentWrapperAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupContentWrappersEntry());
Assert.Throws<XamlSchemaException>(() => type.ContentWrappers);
}
[ContentWrapper(typeof(int))]
private class ClassWithContentWrapperAttribute : Collection<string>
{
}
[ContentWrapper(typeof(string))]
private class InheritedClassWithContentWrapperAttribute : ClassWithContentWrapperAttribute
{
}
[ContentWrapper(null!)]
private class ClassWithNullContentWrapperAttribute : Collection<string>
{
}
[Fact]
public void LookupCustomAttributeProvider_Unknown_ReturnsNull()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.Null(type.LookupCustomAttributeProviderEntry());
}
[Fact]
public void LookupCustomAttributeProvider_UnderlyingType_ReturnsNull()
{
var type = new SubXamlType("namespace", "name", null, new XamlSchemaContext());
Assert.Null(type.LookupCustomAttributeProviderEntry());
}
public static IEnumerable<object?[]> LookupDeferringLoader_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlDeferLoadAttribute(typeof(int), typeof(string)) }
}
},
new XamlValueConverter<XamlDeferringLoader>(typeof(int), null)
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlDeferLoadAttribute(typeof(int), typeof(string)) }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithTypeXamlDeferLoadAttribute), new XamlSchemaContext()),
new XamlValueConverter<XamlDeferringLoader>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithTypeXamlDeferLoadAttribute), new XamlSchemaContext()),
new XamlValueConverter<XamlDeferringLoader>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithStringXamlDeferLoadAttribute)), new XamlSchemaContext()),
new XamlValueConverter<XamlDeferringLoader>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithTypeXamlDeferLoadAttribute), new XamlSchemaContext())
{
LookupDeferringLoaderResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupDeferringLoader_TestData))]
public void LookupDeferringLoader_Invoke_ReturnsExpected(SubXamlType type, XamlValueConverter<XamlDeferringLoader> expected)
{
Assert.Equal(expected, type.LookupDeferringLoaderEntry());
Assert.Equal(expected, type.DeferringLoader);
}
[Fact]
public void LookupDeferringLoader_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupDeferringLoaderEntry());
Assert.Throws<NullReferenceException>(() => type.DeferringLoader);
}
[Fact]
public void LookupDeferringLoader_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupDeferringLoaderEntry());
Assert.Throws<NullReferenceException>(() => type.DeferringLoader);
}
[Fact]
public void LookupDeferringLoader_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupDeferringLoaderEntry());
Assert.Throws<InvalidCastException>(() => type.DeferringLoader);
}
public static IEnumerable<object[]> LookupDeferringLoader_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupDeferringLoader_InvalidAttribute_TestData))]
public void LookupDeferringLoader_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(List<int>))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XamlDeferLoadAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupDeferringLoaderEntry());
Assert.Throws<XamlSchemaException>(() => type.DeferringLoader);
}
[Theory]
[InlineData(typeof(ClassWithNullLoaderTypeXamlDeferLoadAttribute))]
[InlineData(typeof(ClassWithNullContentTypeXamlDeferLoadAttribute))]
[InlineData(typeof(ClassWithNoSuchLoaderTypeNameXamlDeferLoadAttribute))]
[InlineData(typeof(ClassWithNoSuchContentTypeNameXamlDeferLoadAttribute))]
public void LookupDeferringLoader_InvalidParametersType_ThrowsXamlSchemaException(Type underlyingType)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupDeferringLoaderEntry());
Assert.Throws<XamlSchemaException>(() => type.DeferringLoader);
}
[Theory]
[InlineData(typeof(ClassWithNullLoaderTypeNameXamlDeferLoadAttribute))]
[InlineData(typeof(ClassWithNullContentTypeNameXamlDeferLoadAttribute))]
public void LookupDeferringLoader_NullParametersTypeNames_ThrowsXamlSchemaException(Type underlyingType)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("typeName", () => type.LookupDeferringLoaderEntry());
Assert.Throws<ArgumentNullException>("typeName", () => type.DeferringLoader);
}
[XamlDeferLoad(typeof(int), typeof(string))]
public class ClassWithTypeXamlDeferLoadAttribute
{
}
[XamlDeferLoad("System.Int32", "System.String")]
public class ClassWithStringXamlDeferLoadAttribute
{
}
[XamlDeferLoad(null!, typeof(string))]
public class ClassWithNullLoaderTypeXamlDeferLoadAttribute
{
}
[XamlDeferLoad(null!, typeof(string))]
public class ClassWithNullContentTypeXamlDeferLoadAttribute
{
}
[XamlDeferLoad(null!, "System.String")]
public class ClassWithNullLoaderTypeNameXamlDeferLoadAttribute
{
}
[XamlDeferLoad("System.Int32", null!)]
public class ClassWithNullContentTypeNameXamlDeferLoadAttribute
{
}
[XamlDeferLoad("NoSuchType", "System.String")]
public class ClassWithNoSuchLoaderTypeNameXamlDeferLoadAttribute
{
}
[XamlDeferLoad("System.Int32", "NoSuchType")]
public class ClassWithNoSuchContentTypeNameXamlDeferLoadAttribute
{
}
public class InheritedClassWithTypeXamlDeferLoadAttribute : ClassWithTypeXamlDeferLoadAttribute
{
}
[Fact]
public void LookupInvoker_Unknown_ReturnsExpected()
{
var type = new SubXamlType("namespace", "name", null, new XamlSchemaContext());
Assert.Null(type.LookupInvokerEntry());
Assert.Equal(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
[Fact]
public void LookupInvoker_UnderlyingType_ReturnsExpected()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.NotNull(type.LookupInvokerEntry());
Assert.NotNull(type.Invoker);
}
[Fact]
public void LookupInvoker_NullResult_ReturnsExpected()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupInvokerResult = null
};
Assert.Null(type.LookupInvokerEntry());
Assert.Equal(XamlTypeInvoker.UnknownInvoker, type.Invoker);
}
public static IEnumerable<object[]> LookupIsAmbient_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(object), new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
// Has provider.
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
true
};
yield return new object[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
false
};
// Has attribute.
yield return new object[]
{
new SubXamlType(typeof(ClassWithAmbientAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(typeof(InheritedClassWithAmbientAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithAmbientAttribute)), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
false
};
yield return new object[]
{
new CustomXamlType(typeof(ClassWithAmbientAttribute), new XamlSchemaContext())
{
LookupIsAmbientResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsAmbient_TestData))]
public void LookupIsAmbient_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsAmbientEntry());
Assert.Equal(expected, type.IsAmbient);
}
[Ambient]
private class ClassWithAmbientAttribute
{
}
private class InheritedClassWithAmbientAttribute : ClassWithAmbientAttribute
{
}
public static IEnumerable<object[]> LookupIsConstructible_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), true };
yield return new object[] { new NoUnderlyingOrBaseType(), true };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(AbstractClass), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(IConvertible), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(NestedClass), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(List<>), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(List<>).GetTypeInfo().GenericTypeParameters[0], new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ClassWithDefaultConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ClassWithInternalDefaultConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ClassWithProtectedDefaultConstructor), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(ClassWithPrivateDefaultConstructor), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(ClassWithCustomConstructor), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(StaticClass), new XamlSchemaContext()), false };
yield return new object[]
{
new CustomXamlType(typeof(ClassWithCustomConstructor), new XamlSchemaContext())
{
LookupIsConstructibleResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsConstructible_TestData))]
public void LookupIsConstructible_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsConstructibleEntry());
Assert.Equal(expected, type.IsConstructible);
}
public static IEnumerable<object[]> LookupIsMarkupExtension_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
yield return new object[] { new SubXamlType(typeof(MarkupExtension), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(ArrayExtension), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[]
{
new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupIsMarkupExtensionResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsMarkupExtension_TestData))]
public void LookupIsMarkupExtension_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsMarkupExtensionEntry());
Assert.Equal(expected, type.IsMarkupExtension);
}
public static IEnumerable<object?[]> LookupIsNameScope_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object?[] { new NoUnderlyingOrBaseType(), false };
yield return new object?[] { new SubXamlType(typeof(INameScope), new XamlSchemaContext()), true };
yield return new object?[] { new SubXamlType(typeof(INameScopeDictionary), new XamlSchemaContext()), true };
yield return new object?[] { new SubXamlType(typeof(CustomNameScope), new XamlSchemaContext()), true };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object?[]
{
new CustomXamlType(typeof(INameScope), new XamlSchemaContext())
{
LookupIsNameScopeResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsNameScope_TestData))]
public void LookupIsNameScope_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsNameScopeEntry());
Assert.Equal(expected, type.IsNameScope);
}
#pragma warning disable CS8644
private class CustomNameScopeDictionary : Dictionary<string, object>, INameScopeDictionary
{
public void RegisterName(string name, object scopedElement)
{
}
public void UnregisterName(string name)
{
}
public object FindName(string name) => null!;
}
#pragma warning restore CS8644
private class CustomNameScope : INameScope
{
public void RegisterName(string name, object scopedElement)
{
}
public void UnregisterName(string name)
{
}
public object FindName(string name) => null!;
}
public static IEnumerable<object[]> LookupIsNullable_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), true };
yield return new object[] { new NoUnderlyingOrBaseType(), true };
yield return new object[] { new SubXamlType(typeof(int?), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(System.Nullable<>), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(Nullable<int>), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(Generic<int>), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(KeyValuePair<int, string>), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(string), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), true };
yield return new object[]
{
new SubXamlType(new ReflectionOnlyType(typeof(Nullable<int>))
{
AssemblyDelegator = new CustomAssembly(typeof(System.Nullable<>).Assembly)
{
ReflectionOnlyResult = true
}
},
new XamlSchemaContext()), false
};
yield return new object[]
{
new CustomXamlType(typeof(int?), new XamlSchemaContext())
{
LookupIsNullableResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsNullable_TestData))]
public void LookupIsNullable_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsNullableEntry());
Assert.Equal(expected, type.IsNullable);
}
private struct Generic<T> { }
private struct Nullable<T> { }
public static IEnumerable<object[]> LookupIsPublic_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), true };
yield return new object[] { new NoUnderlyingOrBaseType(), true };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(Generic<>), new XamlSchemaContext()), false };
yield return new object[]
{
new CustomXamlType(typeof(INameScope), new XamlSchemaContext())
{
LookupIsPublicResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsPublic_TestData))]
public void LookupIsPublic_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsPublicEntry());
Assert.Equal(expected, type.IsPublic);
}
public static IEnumerable<object[]> LookupIsUnknown_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), true, true };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), true, true };
yield return new object[] { new NoUnderlyingOrBaseType(), false, false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false, false };
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupIsUnknownResult = true
},
true, false
};
}
[Theory]
[MemberData(nameof(LookupIsUnknown_TestData))]
public void LookupIsUnknown_Invoke_ReturnsExpected(SubXamlType type, bool expectedLookup, bool expectedIs)
{
Assert.Equal(expectedLookup, type.LookupIsUnknownEntry());
Assert.Equal(expectedIs, type.IsUnknown);
}
public static IEnumerable<object[]> LookupIsWhitespaceSignificantCollection_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false, true };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false, true };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false, false };
yield return new object[] { new SubXamlType(typeof(object), new XamlSchemaContext()), false, false };
yield return new object[] { new NoUnderlyingOrBaseType(), false, false };
// Has provider.
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
true, true
};
yield return new object[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
false, true
};
// Has attribute.
yield return new object[]
{
new SubXamlType(typeof(ClassWithWhitespaceSignificantCollectionAttribute), new XamlSchemaContext()),
true, true
};
yield return new object[]
{
new SubXamlType(typeof(InheritedClassWithWhitespaceSignificantCollectionAttribute), new XamlSchemaContext()),
true, true
};
yield return new object[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithWhitespaceSignificantCollectionAttribute)), new XamlSchemaContext()),
true, true
};
yield return new object[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
false, false
};
yield return new object[]
{
new CustomXamlType(typeof(ClassWithWhitespaceSignificantCollectionAttribute), new XamlSchemaContext())
{
LookupIsWhitespaceSignificantCollectionResult = false
},
false, false
};
}
[Theory]
[MemberData(nameof(LookupIsWhitespaceSignificantCollection_TestData))]
public void LookupIsWhitespaceSignificantCollection_Invoke_ReturnsExpected(SubXamlType type, bool expectedLookup, bool expectedIs)
{
Assert.Equal(expectedLookup, type.LookupIsWhitespaceSignificantCollectionEntry());
Assert.Equal(expectedIs, type.IsWhitespaceSignificantCollection);
}
[WhitespaceSignificantCollection]
private class ClassWithWhitespaceSignificantCollectionAttribute
{
}
private class InheritedClassWithWhitespaceSignificantCollectionAttribute : ClassWithWhitespaceSignificantCollectionAttribute
{
}
public static IEnumerable<object[]> LookupIsXData_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
yield return new object[] { new SubXamlType(typeof(IXmlSerializable), new XamlSchemaContext()), true };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[]
{
new CustomXamlType(typeof(IXmlSerializable), new XamlSchemaContext())
{
LookupIsXDataResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupIsXData_TestData))]
public void LookupIsXData_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupIsXDataEntry());
Assert.Equal(expected, type.IsXData);
}
public static IEnumerable<object?[]> LookupItemType_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
yield return new object?[] { new SubXamlType(typeof(int[]), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(IList), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(AmbiguousIList), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(AmbiguousICollection), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(MultiICollectionImplementer), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(GetEnumeratorClass), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(IDictionary), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(Dictionary<int, string>), new XamlSchemaContext()), new XamlType(typeof(string), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(AmbiguousIDictionary), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
null
};
yield return new object?[]
{
new CustomXamlType(typeof(List<int>), new XamlSchemaContext())
{
LookupItemTypeResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupItemType_TestData))]
public void LookupItemType_Invoke_ReturnsExpected(SubXamlType type, XamlType expected)
{
Assert.Equal(expected, type.LookupItemTypeEntry());
Assert.Equal((type.IsArray || type.IsCollection || type.IsDictionary) ? expected ?? XamlLanguage.Object : null, type.ItemType);
}
[Theory]
[InlineData(typeof(MultipleICollection))]
[InlineData(typeof(MultipleIDictionary))]
public void LookupItemType_MultipleAddMethods_ThrowsXamlSchemaException(Type underlyingType)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupItemTypeEntry());
Assert.Throws<XamlSchemaException>(() => type.ItemType);
}
public static IEnumerable<object?[]> LookupKeyType_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
yield return new object?[] { new SubXamlType(typeof(int[]), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(IList), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(List<int>), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(AmbiguousIList), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(AmbiguousICollection), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(MultiICollectionImplementer), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(GetEnumeratorClass), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(IDictionary), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(Dictionary<int, string>), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()) };
yield return new object?[] { new SubXamlType(typeof(AmbiguousIDictionary), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()) };
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
null
};
yield return new object?[]
{
new CustomXamlType(typeof(Dictionary<int, string>), new XamlSchemaContext())
{
LookupKeyTypeResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupKeyType_TestData))]
public void LookupKeyType_Invoke_ReturnsExpected(SubXamlType type, XamlType expected)
{
Assert.Equal(expected, type.LookupKeyTypeEntry());
Assert.Equal(type.IsDictionary ? expected ?? XamlLanguage.Object : null, type.KeyType);
}
[Theory]
[InlineData(typeof(MultipleICollection))]
[InlineData(typeof(MultipleIDictionary))]
public void LookupKeyType_MultipleAddMethods_ThrowsXamlSchemaException(Type underlyingType)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupKeyTypeEntry());
if (type.IsDictionary)
{
Assert.Throws<XamlSchemaException>(() => type.KeyType);
}
else
{
Assert.Null(type.KeyType);
}
}
#pragma warning disable IDE0060, IDE0051 // Remove unused parameter, Remove unused member
private class MultipleICollection : ICollection<object>, ICollection<int>
{
int ICollection<object>.Count => throw new NotImplementedException();
int ICollection<int>.Count => throw new NotImplementedException();
bool ICollection<object>.IsReadOnly => throw new NotImplementedException();
bool ICollection<int>.IsReadOnly => throw new NotImplementedException();
void ICollection<object>.Add(object item) => throw new NotImplementedException();
void ICollection<int>.Add(int item) => throw new NotImplementedException();
void ICollection<object>.Clear() => throw new NotImplementedException();
void ICollection<int>.Clear() => throw new NotImplementedException();
bool ICollection<object>.Contains(object item) => throw new NotImplementedException();
bool ICollection<int>.Contains(int item) => throw new NotImplementedException();
void ICollection<object>.CopyTo(object[] array, int arrayIndex) => throw new NotImplementedException();
void ICollection<int>.CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
IEnumerator<object> IEnumerable<object>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
IEnumerator<int> IEnumerable<int>.GetEnumerator() => throw new NotImplementedException();
bool ICollection<object>.Remove(object item) => throw new NotImplementedException();
bool ICollection<int>.Remove(int item) => throw new NotImplementedException();
}
private class MultipleIDictionary : IDictionary<string, int>, IDictionary<int, string>
{
int IDictionary<string, int>.this[string key] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
string IDictionary<int, string>.this[int key] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
ICollection<string> IDictionary<string, int>.Keys => throw new NotImplementedException();
ICollection<int> IDictionary<int, string>.Keys => throw new NotImplementedException();
ICollection<int> IDictionary<string, int>.Values => throw new NotImplementedException();
ICollection<string> IDictionary<int, string>.Values => throw new NotImplementedException();
int ICollection<KeyValuePair<string, int>>.Count => throw new NotImplementedException();
int ICollection<KeyValuePair<int, string>>.Count => throw new NotImplementedException();
bool ICollection<KeyValuePair<string, int>>.IsReadOnly => throw new NotImplementedException();
bool ICollection<KeyValuePair<int, string>>.IsReadOnly => throw new NotImplementedException();
void IDictionary<string, int>.Add(string key, int value) => throw new NotImplementedException();
void ICollection<KeyValuePair<string, int>>.Add(KeyValuePair<string, int> item) => throw new NotImplementedException();
void IDictionary<int, string>.Add(int key, string value) => throw new NotImplementedException();
void ICollection<KeyValuePair<int, string>>.Add(KeyValuePair<int, string> item) => throw new NotImplementedException();
void ICollection<KeyValuePair<string, int>>.Clear() => throw new NotImplementedException();
void ICollection<KeyValuePair<int, string>>.Clear() => throw new NotImplementedException();
bool ICollection<KeyValuePair<string, int>>.Contains(KeyValuePair<string, int> item) => throw new NotImplementedException();
bool ICollection<KeyValuePair<int, string>>.Contains(KeyValuePair<int, string> item) => throw new NotImplementedException();
bool IDictionary<string, int>.ContainsKey(string key) => throw new NotImplementedException();
bool IDictionary<int, string>.ContainsKey(int key) => throw new NotImplementedException();
void ICollection<KeyValuePair<string, int>>.CopyTo(KeyValuePair<string, int>[] array, int arrayIndex) => throw new NotImplementedException();
void ICollection<KeyValuePair<int, string>>.CopyTo(KeyValuePair<int, string>[] array, int arrayIndex) => throw new NotImplementedException();
IEnumerator<KeyValuePair<string, int>> IEnumerable<KeyValuePair<string, int>>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
IEnumerator<KeyValuePair<int, string>> IEnumerable<KeyValuePair<int, string>>.GetEnumerator() => throw new NotImplementedException();
bool IDictionary<string, int>.Remove(string key) => throw new NotImplementedException();
bool ICollection<KeyValuePair<string, int>>.Remove(KeyValuePair<string, int> item) => throw new NotImplementedException();
bool IDictionary<int, string>.Remove(int key) => throw new NotImplementedException();
bool ICollection<KeyValuePair<int, string>>.Remove(KeyValuePair<int, string> item) => throw new NotImplementedException();
bool IDictionary<string, int>.TryGetValue(string key, out int value) => throw new NotImplementedException();
bool IDictionary<int, string>.TryGetValue(int key, out string value) => throw new NotImplementedException();
}
private class AmbiguousICollection : ICollection
{
public int Count => throw new NotImplementedException();
public object SyncRoot => throw new NotImplementedException();
public bool IsSynchronized => throw new NotImplementedException();
public void CopyTo(Array array, int index) => throw new NotImplementedException();
public IEnumerator GetEnumerator() => throw new NotImplementedException();
}
private class AmbiguousIList : AmbiguousICollection, IList
{
public void Add(int value)
{
}
public void Add(string value)
{
}
public object? this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool IsReadOnly => throw new NotImplementedException();
public bool IsFixedSize => throw new NotImplementedException();
public int Add(object? value) => throw new NotImplementedException();
public void Clear() => throw new NotImplementedException();
public bool Contains(object? value) => throw new NotImplementedException();
public int IndexOf(object? value) => throw new NotImplementedException();
public void Insert(int index, object? value) => throw new NotImplementedException();
public void Remove(object? value) => throw new NotImplementedException();
public void RemoveAt(int index) => throw new NotImplementedException();
}
private class AmbiguousIDictionary : IDictionary
{
public void Add(string key, int value)
{
}
public void Add(int key, string value)
{
}
public object? this[object key] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public ICollection Keys => throw new NotImplementedException();
public ICollection Values => throw new NotImplementedException();
public bool IsReadOnly => throw new NotImplementedException();
public bool IsFixedSize => throw new NotImplementedException();
public int Count => throw new NotImplementedException();
public object SyncRoot => throw new NotImplementedException();
public bool IsSynchronized => throw new NotImplementedException();
public void Add(object key, object? value) => throw new NotImplementedException();
public void Clear() => throw new NotImplementedException();
public bool Contains(object key) => throw new NotImplementedException();
public void CopyTo(Array array, int index) => throw new NotImplementedException();
public IDictionaryEnumerator GetEnumerator() => throw new NotImplementedException();
public void Remove(object key) => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
}
#pragma warning restore IDE0060, IDE0051 // Remove unused parameter, Remove unused member
public static IEnumerable<object?[]> LookupMarkupExtensionReturnType_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(MarkupExtension), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new MarkupExtensionReturnTypeAttribute(typeof(int)) }
}
},
new XamlType(typeof(int), new XamlSchemaContext())
};
yield return new object?[]
{
new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new MarkupExtensionReturnTypeAttribute(typeof(int)) }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithMarkupExtensionReturnTypeAttribute), new XamlSchemaContext()),
new XamlType(typeof(int), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithMarkupExtensionReturnTypeAttribute), new XamlSchemaContext()),
new XamlType(typeof(int), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithMarkupExtensionReturnTypeAttribute)), new XamlSchemaContext()),
new XamlType(typeof(int), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(MarkupExtension)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithMarkupExtensionReturnTypeAttribute), new XamlSchemaContext())
{
LookupMarkupExtensionReturnTypeResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupMarkupExtensionReturnType_TestData))]
public void LookupMarkupExtensionReturnType_Invoke_ReturnsExpected(SubXamlType type, XamlType expected)
{
Assert.Equal(expected, type.LookupMarkupExtensionReturnTypeEntry());
Assert.Equal(type.IsMarkupExtension ? expected ?? XamlLanguage.Object : null, type.MarkupExtensionReturnType);
}
[Fact]
public void LookupMarkupExtensionReturnType_NullTypeInAttribute_ThrowsXamlSchemaException()
{
var type = new SubXamlType(typeof(ClassWithNullMarkupExtensionReturnTypeAttribute), new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupMarkupExtensionReturnTypeEntry());
Assert.Throws<XamlSchemaException>(() => type.MarkupExtensionReturnType);
}
[Fact]
public void LookupMarkupExtensionReturnType_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupMarkupExtensionReturnTypeEntry());
Assert.Throws<NullReferenceException>(() => type.MarkupExtensionReturnType);
}
[Fact]
public void LookupMarkupExtensionReturnType_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupMarkupExtensionReturnTypeEntry());
Assert.Throws<NullReferenceException>(() => type.MarkupExtensionReturnType);
}
[Fact]
public void LookupMarkupExtensionReturnType_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupMarkupExtensionReturnTypeEntry());
Assert.Throws<InvalidCastException>(() => type.MarkupExtensionReturnType);
}
[MarkupExtensionReturnType(typeof(int))]
private class ClassWithMarkupExtensionReturnTypeAttribute : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider) => null!;
}
private class InheritedClassWithMarkupExtensionReturnTypeAttribute : ClassWithMarkupExtensionReturnTypeAttribute
{
}
[MarkupExtensionReturnType(null)]
private class ClassWithNullMarkupExtensionReturnTypeAttribute : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider) => null!;
}
[MarkupExtensionReturnType]
private class ClassWihDefaultMarkupExtensionReturnTypeAttribute : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider) => null!;
}
#pragma warning disable 0618
[MarkupExtensionReturnType(typeof(int), typeof(string))]
#pragma warning restore 0618
private class ClassWihExpressionTypeMarkupExtensionReturnTypeAttribute : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider) => null!;
}
public static IEnumerable<object?[]> LookupMember_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), "name", false, null, null };
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), "", true, null, null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), "name", false, null, null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), "name", false, null, null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), "name", false, null, null };
yield return new object?[] { new NoUnderlyingOrBaseType(), "name", true, null, null };
yield return new object?[] { new NoUnderlyingOrBaseType(), "name", false, null, null };
// Property.
foreach (bool skipReadOnlyCheck in new bool[] { true, false })
{
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"Property", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.Property)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.Property)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"GetOnlyListProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyListProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyListProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"GetOnlyDictionaryProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyDictionaryProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyDictionaryProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"GetXDataProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetXDataProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetXDataProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"SetOnlyProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.SetOnlyProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.SetOnlyProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"PrivateGetProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateGetProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateGetProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"PrivateSetProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateSetProperty)), new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.PrivateSetProperty)), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MoreDerivedShadowedDataClass), new XamlSchemaContext()),
"Property", skipReadOnlyCheck,
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!, new XamlSchemaContext()),
new XamlMember(typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(new CustomType(typeof(EvenMoreDerivedShadowedBaseClass))
{
GetMemberResult = new MemberInfo[]
{
typeof(ShadowedBaseClass).GetProperty(nameof(ShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!
}
}, new XamlSchemaContext()),
"Property", skipReadOnlyCheck,
new XamlMember(typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!, new XamlSchemaContext()),
new XamlMember(typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(new CustomType(typeof(EvenMoreDerivedShadowedBaseClass))
{
GetMemberResult = new MemberInfo[]
{
typeof(ShadowedBaseClass).GetProperty(nameof(ShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
typeof(MoreDerivedShadowedDataClass).GetProperty(nameof(MoreDerivedShadowedDataClass.Property), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)!,
}
}, new XamlSchemaContext()),
"Property", skipReadOnlyCheck,
new XamlMember(typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property)!, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext()),
new XamlMember(typeof(EvenMoreDerivedShadowedBaseClass).GetProperty(nameof(EvenMoreDerivedShadowedBaseClass.Property)!, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"Item", skipReadOnlyCheck,
null,
null
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"ProtectedProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty("ProtectedProperty", BindingFlags.Instance | BindingFlags.NonPublic)!, new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty("ProtectedProperty", BindingFlags.Instance | BindingFlags.NonPublic)!, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"InternalProperty", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.InternalProperty), BindingFlags.Instance | BindingFlags.NonPublic)!, new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.InternalProperty), BindingFlags.Instance | BindingFlags.NonPublic)!, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"PrivateProperty", skipReadOnlyCheck,
null,
null
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"StaticProperty", skipReadOnlyCheck,
null,
null
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"NoSuchProperty", skipReadOnlyCheck,
null,
null
};
}
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"GetOnlyProperty", false,
null,
null
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"GetOnlyProperty", true,
new XamlMember(typeof(MembersDataClass).GetProperty(nameof(MembersDataClass.GetOnlyProperty))!, new XamlSchemaContext()),
null
};
// Event.
foreach (bool skipReadOnlyCheck in new bool[] { true, false })
{
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"Event", skipReadOnlyCheck,
new XamlMember(typeof(MembersDataClass).GetEvent(nameof(MembersDataClass.Event))!, new XamlSchemaContext()),
new XamlMember(typeof(MembersDataClass).GetEvent(nameof(MembersDataClass.Event))!, new XamlSchemaContext())
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"PrivateEvent", skipReadOnlyCheck,
null,
null
};
yield return new object?[]
{
new SubXamlType(typeof(MembersDataClass), new XamlSchemaContext()),
"StaticEvent", skipReadOnlyCheck,
null,
null
};
}
yield return new object?[]
{
new CustomXamlType(typeof(MembersDataClass), new XamlSchemaContext())
{
LookupMemberResult = null
},
"name", false,
null,
null
};
}
[Theory]
[MemberData(nameof(LookupMember_TestData))]
public void LookupMember_Invoke_ReturnsExpected(SubXamlType type, string name, bool skipReadOnlyCheck, XamlMember expectedLookup, XamlMember expectedGet)
{
Assert.Equal(expectedLookup, type.LookupMemberEntry(name, skipReadOnlyCheck));
Assert.Equal(expectedGet, type.GetMember(name));
}
[Fact]
public void LookupMember_NullName_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("name", () => type.LookupMemberEntry(null!, false));
Assert.Throws<ArgumentNullException>("key", () => type.GetMember(null));
}
[Fact]
public void LookupMember_NullNameUnknownNoBaseType_ThrowsArgumentNullExceptionOnGetter()
{
var type = new NoUnderlyingOrBaseType();
Assert.Null(type.LookupMemberEntry(null!, false));
Assert.Throws<ArgumentNullException>("key", () => type.GetMember(null));
}
public static IEnumerable<object?[]> LookupPositionalParameters_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), 1, null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), 1, null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), 1, null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), -1, null };
yield return new object?[] { new SubXamlType(typeof(MarkupExtension), new XamlSchemaContext()), 1, null };
yield return new object?[] { new NoUnderlyingOrBaseType(), 1, null };
yield return new object?[] { new SubXamlType(typeof(ClassWithCustomConstructor), new XamlSchemaContext()), 1, new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) } };
yield return new object?[] { new SubXamlType(typeof(TypeExtension), new XamlSchemaContext()), 2, null };
yield return new object?[] { new SubXamlType(typeof(TypeExtension), new XamlSchemaContext()), 1, new XamlType[] { new XamlType(typeof(Type), new XamlSchemaContext()) } };
yield return new object?[] { new SubXamlType(typeof(TypeExtension), new XamlSchemaContext()), 0, null };
yield return new object?[] { new SubXamlType(typeof(TypeExtension), new XamlSchemaContext()), -1, null };
var duplicateSupport = new XamlSchemaContextSettings { SupportMarkupExtensionsWithDuplicateArity = true };
yield return new object?[] { new SubXamlType(typeof(ArrayExtension), new XamlSchemaContext(duplicateSupport)), 2, null };
yield return new object?[] { new SubXamlType(typeof(ArrayExtension), new XamlSchemaContext(duplicateSupport)), 1, new XamlType[] { new XamlType(typeof(Type), new XamlSchemaContext()) } };
yield return new object?[] { new SubXamlType(typeof(ArrayExtension), new XamlSchemaContext(duplicateSupport)), 0, Array.Empty<XamlType>() };
yield return new object?[] { new SubXamlType(typeof(ArrayExtension), new XamlSchemaContext(duplicateSupport)), -1, null };
yield return new object?[]
{
new CustomXamlType(typeof(ArrayExtension), new XamlSchemaContext())
{
LookupPositionalParametersResult = null
},
0, null
};
}
[Theory]
[MemberData(nameof(LookupPositionalParameters_TestData))]
public void LookupPositionalParameters_Invoke_ReturnsExpected(SubXamlType type, int parameterCount, IList<XamlType> expected)
{
Assert.Equal(expected, type.LookupPositionalParametersEntry(parameterCount));
Assert.Equal(expected, type.GetPositionalParameters(parameterCount));
}
[Theory]
[InlineData(typeof(ArrayExtension), 0)]
[InlineData(typeof(ArrayExtension), 1)]
[InlineData(typeof(ArrayExtension), 2)]
public void LookupPositionalParameters_DuplicatesNotSupported_ThrowsXamlSchemaException(Type underlyingType, int parameterCount)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupPositionalParametersEntry(parameterCount));
Assert.Throws<XamlSchemaException>(() => type.GetPositionalParameters(parameterCount));
}
public static IEnumerable<object?[]> LookupSetMarkupExtensionHandler_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithXamlSetMarkupExtensionEventArgsDelegate), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetMarkupExtensionAttribute("Method") }
}
},
Delegate.CreateDelegate(typeof(EventHandler<XamlSetMarkupExtensionEventArgs>), typeof(ClassWithXamlSetMarkupExtensionEventArgsDelegate), "Method")
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetMarkupExtensionAttribute("name") }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithXamlSetMarkupExtensionAttribute), new XamlSchemaContext()),
Delegate.CreateDelegate(typeof(EventHandler<XamlSetMarkupExtensionEventArgs>), typeof(ClassWithXamlSetMarkupExtensionAttribute), "Method")
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithXamlSetMarkupExtensionAttribute), new XamlSchemaContext()),
Delegate.CreateDelegate(typeof(EventHandler<XamlSetMarkupExtensionEventArgs>), typeof(InheritedClassWithXamlSetMarkupExtensionAttribute), "Method")
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullXamlSetMarkupExtensionAttribute), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithXamlSetMarkupExtensionAttribute), new XamlSchemaContext())
{
LookupSetMarkupExtensionHandlerResult = null
},
null
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
null
};
}
[Theory]
[MemberData(nameof(LookupSetMarkupExtensionHandler_TestData))]
public void LookupSetMarkupExtensionHandler_Invoke_ReturnsExpected(SubXamlType type, EventHandler<XamlSetMarkupExtensionEventArgs> expected)
{
Assert.Equal(expected, type.LookupSetMarkupExtensionHandlerEntry());
}
[Fact]
public void LookupSetMarkupExtensionHandler_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupSetMarkupExtensionHandlerEntry());
}
[Fact]
public void LookupSetMarkupExtensionHandler_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupSetMarkupExtensionHandlerEntry());
}
[Fact]
public void LookupSetMarkupExtensionHandler_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupSetMarkupExtensionHandlerEntry());
}
public static IEnumerable<object[]> LookupSetMarkupExtensionHandler_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupSetMarkupExtensionHandler_InvalidAttribute_TestData))]
public void LookupSetMarkupExtensionHandler_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(int))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XamlSetMarkupExtensionAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupSetMarkupExtensionHandlerEntry());
}
[Fact]
public void LookupSetMarkupExtensionHandler_NoSuchName_ThrowsArgumentException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetMarkupExtensionAttribute("name") }
}
};
Assert.Throws<ArgumentException>(() => type.LookupSetMarkupExtensionHandlerEntry());
}
[Fact]
public void LookupSetMarkupExtensionHandler_NotRuntimeType_ThrowsArgumentException()
{
var type = new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithXamlSetMarkupExtensionAttribute)), new XamlSchemaContext());
Assert.Throws<ArgumentException>("target", () => type.LookupSetMarkupExtensionHandlerEntry());
}
#pragma warning disable IDE0060, IDE0051, CA1052 // Remove unused parameter, Remove unused private members, Static holder types should be Static or NotInheritable
private class ClassWithXamlSetMarkupExtensionEventArgsDelegate
{
public static void Method(object sender, XamlSetMarkupExtensionEventArgs e)
{
}
}
[XamlSetMarkupExtension("Method")]
private class ClassWithXamlSetMarkupExtensionAttribute
{
public static void Method(object sender, XamlSetMarkupExtensionEventArgs e)
{
}
}
private class InheritedClassWithXamlSetMarkupExtensionAttribute : ClassWithXamlSetMarkupExtensionAttribute
{
}
[XamlSetMarkupExtension(null!)]
private class ClassWithNullXamlSetMarkupExtensionAttribute
{
}
#pragma warning restore IDE0060, IDE0051, CA1052 // Remove unused parameter, Remove unused private members, Static holder types should be Static or NotInheritable
public static IEnumerable<object?[]> LookupSetTypeConverterHandler_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithXamlSetTypeConverterEventArgsDelegate), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetTypeConverterAttribute("Method") }
}
},
Delegate.CreateDelegate(typeof(EventHandler<XamlSetTypeConverterEventArgs>), typeof(ClassWithXamlSetTypeConverterEventArgsDelegate), "Method")
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetTypeConverterAttribute("name") }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithXamlSetTypeConverterAttribute), new XamlSchemaContext()),
Delegate.CreateDelegate(typeof(EventHandler<XamlSetTypeConverterEventArgs>), typeof(ClassWithXamlSetTypeConverterAttribute), "Method")
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithXamlSetTypeConverterAttribute), new XamlSchemaContext()),
Delegate.CreateDelegate(typeof(EventHandler<XamlSetTypeConverterEventArgs>), typeof(InheritedClassWithXamlSetTypeConverterAttribute), "Method")
};
yield return new object?[]
{
new SubXamlType(typeof(ClassWithNullXamlSetTypeConverterAttribute), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithXamlSetTypeConverterAttribute), new XamlSchemaContext())
{
LookupSetTypeConverterHandlerResult = null
},
null
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupBaseTypeResult = new XamlType("namespace", "name", null, new XamlSchemaContext())
},
null
};
}
[Theory]
[MemberData(nameof(LookupSetTypeConverterHandler_TestData))]
public void LookupSetTypeConverterHandler_Invoke_ReturnsExpected(SubXamlType type, EventHandler<XamlSetTypeConverterEventArgs> expected)
{
Assert.Equal(expected, type.LookupSetTypeConverterHandlerEntry());
}
[Fact]
public void LookupSetTypeConverterHandlerEntry_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupSetTypeConverterHandlerEntry());
}
[Fact]
public void LookupSetTypeConverterHandler_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupSetTypeConverterHandlerEntry());
}
[Fact]
public void LookupSetTypeConverterHandler_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupSetTypeConverterHandlerEntry());
}
public static IEnumerable<object[]> LookupSetTypeConverterHandler_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupSetTypeConverterHandler_InvalidAttribute_TestData))]
public void LookupSetTypeConverterHandler_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(int))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(XamlSetTypeConverterAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupSetTypeConverterHandlerEntry());
}
[Fact]
public void LookupSetTypeConverterHandler_NoSuchName_ThrowsArgumentException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new XamlSetTypeConverterAttribute("name") }
}
};
Assert.Throws<ArgumentException>(() => type.LookupSetTypeConverterHandlerEntry());
}
[Fact]
public void LookupSetTypeConverterHandler_NotRuntimeType_ThrowsArgumentException()
{
var type = new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithXamlSetTypeConverterAttribute)), new XamlSchemaContext());
Assert.Throws<ArgumentException>("target", () => type.LookupSetTypeConverterHandlerEntry());
}
#pragma warning disable CA1052 // Static holder types should be Static or NotInheritable
private class ClassWithXamlSetTypeConverterEventArgsDelegate
{
public static void Method(object sender, XamlSetTypeConverterEventArgs e)
{
}
}
[XamlSetTypeConverter("Method")]
private class ClassWithXamlSetTypeConverterAttribute
{
public static void Method(object sender, XamlSetTypeConverterEventArgs e)
{
}
}
private class InheritedClassWithXamlSetTypeConverterAttribute : ClassWithXamlSetTypeConverterAttribute
{
}
[XamlSetTypeConverter(null!)]
private class ClassWithNullXamlSetTypeConverterAttribute
{
}
#pragma warning restore CA1052 // Static holder types should be Static or NotInheritable
public static IEnumerable<object[]> LookupTrimSurroundingWhitespace_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(object), new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
// Has provider.
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
true
};
yield return new object[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
IsDefinedAction = (attributeType, inherit) => true
}
},
false
};
// Has attribute.
yield return new object[]
{
new SubXamlType(typeof(ClassWithTrimSurroundingWhitespaceAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(typeof(InheritedClassWithTrimSurroundingWhitespaceAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithTrimSurroundingWhitespaceAttribute)), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
false
};
yield return new object[]
{
new CustomXamlType(typeof(ClassWithTrimSurroundingWhitespaceAttribute), new XamlSchemaContext())
{
LookupTrimSurroundingWhitespaceResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupTrimSurroundingWhitespace_TestData))]
public void LookupTrimSurroundingWhitespace_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupTrimSurroundingWhitespaceEntry());
Assert.Equal(expected, type.TrimSurroundingWhitespace);
}
[TrimSurroundingWhitespace]
private class ClassWithTrimSurroundingWhitespaceAttribute
{
}
private class InheritedClassWithTrimSurroundingWhitespaceAttribute : ClassWithTrimSurroundingWhitespaceAttribute
{
}
public static IEnumerable<object?[]> LookupTypeConverter_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(byte), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(ByteConverter), null) };
yield return new object?[] { new SubXamlType(typeof(sbyte), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(SByteConverter), null) };
yield return new object?[] { new SubXamlType(typeof(ushort), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(UInt16Converter), null) };
yield return new object?[] { new SubXamlType(typeof(short), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(Int16Converter), null) };
yield return new object?[] { new SubXamlType(typeof(uint), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(UInt32Converter), null) };
yield return new object?[] { new SubXamlType(typeof(int), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(Int32Converter), null) };
yield return new object?[] { new SubXamlType(typeof(ulong), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(UInt64Converter), null) };
yield return new object?[] { new SubXamlType(typeof(long), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(Int64Converter), null) };
yield return new object?[] { new SubXamlType(typeof(char), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(CharConverter), null) };
yield return new object?[] { new SubXamlType(typeof(bool), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(BooleanConverter), null) };
yield return new object?[] { new SubXamlType(typeof(float), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(SingleConverter), null) };
yield return new object?[] { new SubXamlType(typeof(double), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(DoubleConverter), null) };
yield return new object?[] { new SubXamlType(typeof(decimal), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(DecimalConverter), null) };
yield return new object?[] { new SubXamlType(typeof(string), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(StringConverter), null) };
yield return new object?[] { new SubXamlType(typeof(TimeSpan), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(TimeSpanConverter), null) };
yield return new object?[] { new SubXamlType(typeof(Guid), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(GuidConverter), null) };
yield return new object?[] { new SubXamlType(typeof(CultureInfo), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(CultureInfoConverter), null) };
yield return new object?[] { new SubXamlType(typeof(ConsoleColor), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(EnumConverter), new XamlType(typeof(ConsoleColor), new XamlSchemaContext())) };
yield return new object?[] { new SubXamlType(typeof(int?), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(typeof(Int32Converter), null) };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), new XamlValueConverter<TypeConverter>(null, XamlLanguage.Object) };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new TypeConverterAttribute(typeof(string)) }
}
},
new XamlValueConverter<TypeConverter>(typeof(string), null)
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
new XamlValueConverter<TypeConverter>(typeof(Int32Converter), null)
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new TypeConverterAttribute(typeof(int)) }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithTypeConverterAttribute), new XamlSchemaContext()),
new XamlValueConverter<TypeConverter>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(typeof(StructWithTypeConverterAttribute?), new XamlSchemaContext()),
new XamlValueConverter<TypeConverter>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithTypeConverterAttribute), new XamlSchemaContext()),
new XamlValueConverter<TypeConverter>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithStringTypeConverterAttribute)), new XamlSchemaContext()),
new XamlValueConverter<TypeConverter>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithTypeConverterAttribute), new XamlSchemaContext())
{
LookupTypeConverterResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupTypeConverter_TestData))]
public void LookupTypeConverter_Invoke_ReturnsExpected(SubXamlType type, XamlValueConverter<TypeConverter> expected)
{
Assert.Equal(expected, type.LookupTypeConverterEntry());
Assert.Equal(expected, type.TypeConverter);
}
[Fact]
public void LookupTypeConverter_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupTypeConverterEntry());
Assert.Throws<NullReferenceException>(() => type.TypeConverter);
}
[Fact]
public void LookupTypeConverter_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupTypeConverterEntry());
Assert.Throws<NullReferenceException>(() => type.TypeConverter);
}
[Fact]
public void LookupTypeConverter_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupTypeConverterEntry());
Assert.Throws<InvalidCastException>(() => type.TypeConverter);
}
public static IEnumerable<object[]> LookupTypeConverter_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupTypeConverter_InvalidAttribute_TestData))]
public void LookupTypeConverter_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(List<int>))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(TypeConverterAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupTypeConverterEntry());
Assert.Throws<XamlSchemaException>(() => type.TypeConverter);
}
[Theory]
[InlineData(typeof(ClassWithNullTypeConverterAttribute))]
[InlineData(typeof(ClassWithDefaultTypeConverterAttribute))]
public void LookupTypeConverter_InvalidParametersType_ThrowsXamlSchemaException(Type underlyingType)
{
var type = new SubXamlType(underlyingType, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupTypeConverterEntry());
Assert.Throws<XamlSchemaException>(() => type.TypeConverter);
}
[Fact]
public void LookupTypeConverter_NullStringType_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(ClassWithNullStringTypeConverterAttribute), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("typeName", () => type.LookupTypeConverterEntry());
Assert.Throws<ArgumentNullException>("typeName", () => type.TypeConverter);
}
[TypeConverter(typeof(int))]
public class ClassWithTypeConverterAttribute
{
}
[TypeConverter(typeof(int))]
public struct StructWithTypeConverterAttribute
{
}
[TypeConverter("System.Int32")]
public class ClassWithStringTypeConverterAttribute
{
}
public class InheritedClassWithTypeConverterAttribute : ClassWithTypeConverterAttribute
{
}
[TypeConverter((string)null!)]
public class ClassWithNullStringTypeConverterAttribute
{
}
[TypeConverter((Type)null!)]
public class ClassWithNullTypeConverterAttribute
{
}
[TypeConverter]
public class ClassWithDefaultTypeConverterAttribute
{
}
[Fact]
public void LookupUnderlyingType_Unknown_ReturnsObject()
{
var type = new SubXamlType("namespace", "name", null, new XamlSchemaContext());
Assert.Null(type.LookupUnderlyingTypeEntry());
Assert.Null(type.UnderlyingType);
}
[Fact]
public void LookupUnderlyingType_HasUnderlyingType_ReturnsExpected()
{
var type = new SubXamlType(typeof(int), new XamlSchemaContext());
Assert.Equal(typeof(int), type.LookupUnderlyingTypeEntry());
Assert.Equal(typeof(int), type.UnderlyingType);
}
[Fact]
public void LookupUnderlyingType_NullResult_ReturnsExpected()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupUnderlyingTypeResult = null
};
Assert.Null(type.LookupUnderlyingTypeEntry());
Assert.Equal(typeof(int), type.UnderlyingType);
}
public static IEnumerable<object[]> LookupUsableDuringInitialization_TestData()
{
yield return new object[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(object), new XamlSchemaContext()), false };
yield return new object[] { new SubXamlType(typeof(MarkupExtension), new XamlSchemaContext()), false };
yield return new object[] { new NoUnderlyingOrBaseType(), false };
// Has provider.
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new UsableDuringInitializationAttribute(true) }
}
},
true
};
yield return new object[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
false
};
yield return new object[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new UsableDuringInitializationAttribute(true) }
}
},
false
};
// Has attribute.
yield return new object[]
{
new SubXamlType(typeof(ClassWithUsableDuringInitializationAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(typeof(InheritedClassWithUsableDuringInitializationAttribute), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithUsableDuringInitializationAttribute)), new XamlSchemaContext()),
true
};
yield return new object[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
false
};
yield return new object[]
{
new CustomXamlType(typeof(ClassWithUsableDuringInitializationAttribute), new XamlSchemaContext())
{
LookupUsableDuringInitializationResult = false
},
false
};
}
[Theory]
[MemberData(nameof(LookupUsableDuringInitialization_TestData))]
public void LookupUsableDuringInitialization_Invoke_ReturnsExpected(SubXamlType type, bool expected)
{
Assert.Equal(expected, type.LookupUsableDuringInitializationEntry());
Assert.Equal(expected, type.IsUsableDuringInitialization);
}
[Fact]
public void LookupUsableDuringInitialization_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupUsableDuringInitializationEntry());
Assert.Throws<NullReferenceException>(() => type.IsUsableDuringInitialization);
}
[Fact]
public void LookupUsableDuringInitialization_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupUsableDuringInitializationEntry());
Assert.Throws<NullReferenceException>(() => type.IsUsableDuringInitialization);
}
[Fact]
public void LookupUsableDuringInitialization_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupUsableDuringInitializationEntry());
Assert.Throws<InvalidCastException>(() => type.IsUsableDuringInitialization);
}
[Fact]
public void LookupUsableDuringInitialization_MarkupExtension_ThrowsXamlSchemaException()
{
var type = new CustomXamlType(typeof(MarkupExtension), new XamlSchemaContext())
{
LookupUsableDuringInitializationResult = true
};
Assert.True(type.LookupUsableDuringInitializationEntry());
Assert.Throws<XamlSchemaException>(() => type.IsUsableDuringInitialization);
}
public static IEnumerable<object[]> LookupUsableDuringInitialization_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupUsableDuringInitialization_InvalidAttribute_TestData))]
public void LookupUsableDuringInitialization_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(int))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(UsableDuringInitializationAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupUsableDuringInitializationEntry());
Assert.Throws<XamlSchemaException>(() => type.IsUsableDuringInitialization);
}
[UsableDuringInitializationAttribute(true)]
private class ClassWithUsableDuringInitializationAttribute
{
}
private class InheritedClassWithUsableDuringInitializationAttribute : ClassWithUsableDuringInitializationAttribute
{
}
public static IEnumerable<object?[]> LookupValueSerializer_TestData()
{
yield return new object?[] { new SubXamlType("namespace", "name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(int?), new XamlSchemaContext()), null };
yield return new object?[] { new SubXamlType(typeof(string), new XamlSchemaContext()), new XamlValueConverter<ValueSerializer>(ValueSerializer.GetSerializerFor(typeof(string))!.GetType(), null) };
yield return new object?[] { new SubXamlType(typeof(object), new XamlSchemaContext()), null };
yield return new object?[] { new NoUnderlyingOrBaseType(), null };
// Has provider.
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ValueSerializerAttribute(typeof(string)) }
}
},
new XamlValueConverter<ValueSerializer>(typeof(string), null)
};
yield return new object?[]
{
new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => Array.Empty<object>()
}
},
null
};
yield return new object?[]
{
new CustomXamlType("namespace", "name", null, new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new ValueSerializerAttribute(typeof(int)) }
}
},
null
};
// Has attribute.
yield return new object?[]
{
new SubXamlType(typeof(ClassWithValueSerializerAttribute), new XamlSchemaContext()),
new XamlValueConverter<ValueSerializer>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(typeof(StructWithValueSerializerAttribute?), new XamlSchemaContext()),
new XamlValueConverter<ValueSerializer>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(typeof(InheritedClassWithValueSerializerAttribute), new XamlSchemaContext()),
new XamlValueConverter<ValueSerializer>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ReflectionOnlyCustomAttributeDataType(typeof(ClassWithStringValueSerializerAttribute)), new XamlSchemaContext()),
new XamlValueConverter<ValueSerializer>(typeof(int), null)
};
yield return new object?[]
{
new SubXamlType(new ThrowsCustomAttributeFormatExceptionDelegator(typeof(int)), new XamlSchemaContext()),
null
};
yield return new object?[]
{
new CustomXamlType(typeof(ClassWithValueSerializerAttribute), new XamlSchemaContext())
{
LookupValueSerializerResult = null
},
null
};
}
[Theory]
[MemberData(nameof(LookupValueSerializer_TestData))]
public void LookupValueSerializer_Invoke_ReturnsExpected(SubXamlType type, XamlValueConverter<ValueSerializer> expected)
{
Assert.Equal(expected, type.LookupValueSerializerEntry());
Assert.Equal(expected, type.ValueSerializer);
}
[Fact]
public void LookupValueSerializer_NullAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => null!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupValueSerializerEntry());
Assert.Throws<NullReferenceException>(() => type.ValueSerializer);
}
[Fact]
public void LookupValueSerializer_NullItemInAttributeResult_ThrowsNullReferenceException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object?[] { null }!
}
};
Assert.Throws<NullReferenceException>(() => type.LookupValueSerializerEntry());
Assert.Throws<NullReferenceException>(() => type.ValueSerializer);
}
[Fact]
public void LookupValueSerializer_InvalidTypeItemInAttributeResult_ThrowsInvalidCastException()
{
var type = new CustomXamlType(typeof(int), new XamlSchemaContext())
{
LookupCustomAttributeProviderResult = new CustomAttributeProvider
{
GetCustomAttributesAction = (attributeType, inherit) => new object[] { new object() }
}
};
Assert.Throws<InvalidCastException>(() => type.LookupValueSerializerEntry());
Assert.Throws<InvalidCastException>(() => type.ValueSerializer);
}
public static IEnumerable<object[]> LookupValueSerializer_InvalidAttribute_TestData()
{
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1), new CustomAttributeTypedArgument(typeof(int), 2) } };
yield return new object[] { new CustomAttributeTypedArgument[] { new CustomAttributeTypedArgument(typeof(int), 1) } };
}
[Theory]
[MemberData(nameof(LookupValueSerializer_InvalidAttribute_TestData))]
public void LookupValueSerializer_InvalidAttribute_ThrowsXamlSchemaException(CustomAttributeTypedArgument[] arguments)
{
var type = new SubXamlType(new CustomType(typeof(List<int>))
{
GetCustomAttributesDataResult = new CustomAttributeData[]
{
new CustomCustomAttributeData
{
ConstructorResult = typeof(ValueSerializerAttribute).GetConstructors()[0],
ConstructorArgumentsResult = arguments
}
}
}, new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupValueSerializerEntry());
Assert.Throws<XamlSchemaException>(() => type.ValueSerializer);
}
[Fact]
public void LookupValueSerializer_InvalidParametersType_ThrowsXamlSchemaException()
{
var type = new SubXamlType(typeof(ClassWithNullValueSerializerAttribute), new XamlSchemaContext());
Assert.Throws<XamlSchemaException>(() => type.LookupValueSerializerEntry());
Assert.Throws<XamlSchemaException>(() => type.ValueSerializer);
}
[Fact]
public void LookupValueSerializer_NullStringType_ThrowsArgumentNullException()
{
var type = new SubXamlType(typeof(ClassWithNullStringValueSerializerAttribute), new XamlSchemaContext());
Assert.Throws<ArgumentNullException>("typeName", () => type.LookupValueSerializerEntry());
Assert.Throws<ArgumentNullException>("typeName", () => type.ValueSerializer);
}
[ValueSerializer(typeof(int))]
public class ClassWithValueSerializerAttribute
{
}
[ValueSerializer(typeof(int))]
public struct StructWithValueSerializerAttribute
{
}
[ValueSerializer("System.Int32")]
public class ClassWithStringValueSerializerAttribute
{
}
public class InheritedClassWithValueSerializerAttribute : ClassWithValueSerializerAttribute
{
}
[ValueSerializer((string)null!)]
public class ClassWithNullStringValueSerializerAttribute
{
}
[ValueSerializer((Type)null!)]
public class ClassWithNullValueSerializerAttribute
{
}
public static IEnumerable<object?[]> CanAssignTo_TestData()
{
// Known.
yield return new object?[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()), true };
yield return new object?[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(object), new XamlSchemaContext()), true };
yield return new object?[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(string), new XamlSchemaContext()), false };
yield return new object?[] { new XamlType(typeof(SubXamlType), new XamlSchemaContext()), new XamlType(typeof(XamlType), new XamlSchemaContext()), true };
yield return new object?[] { new XamlType(typeof(XamlType), new XamlSchemaContext()), new XamlType(typeof(SubXamlType), new XamlSchemaContext()), false };
yield return new object?[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType(typeof(int), new XamlSchemaContext()), null, false };
// Unknown.
yield return new object?[] { new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), true };
yield return new object?[] { new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), new XamlType("otherTypeNamespace", "unknownType", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("unknownTypeNamespace", "unknownType", null, new XamlSchemaContext()), null, false };
// ReflectionOnly.
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlType)), new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlType)), new XamlSchemaContext()),
new XamlType(typeof(XamlSchemaContext), new XamlSchemaContext()),
false
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(int)), new XamlSchemaContext()),
new XamlType(typeof(XamlSchemaContext), new XamlSchemaContext()),
false
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlObjectWriterSettings)), new XamlSchemaContext()),
new XamlType(typeof(XamlWriterSettings), new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlWriterSettings)), new XamlSchemaContext()),
new XamlType(typeof(XamlObjectWriterSettings), new XamlSchemaContext()),
false
};
// WindowsBase/System.Xaml.
var differentVersionType = new ReflectionOnlyType(typeof(XamlType));
var differentVersionAssemblyName = new AssemblyName(differentVersionType.Assembly.FullName!)
{
Version = new Version(2, 0)
};
differentVersionType.AssemblyDelegator!.FullNameResult = differentVersionAssemblyName.FullName;
yield return new object?[]
{
new XamlType(differentVersionType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
true
};
var differentCultureType = new ReflectionOnlyType(typeof(XamlType));
var differentCultureAssemblyName = new AssemblyName(differentCultureType.Assembly.FullName!)
{
CultureInfo = new CultureInfo("fr-FR")
};
differentCultureType.AssemblyDelegator!.FullNameResult = differentCultureAssemblyName.FullName;
yield return new object?[]
{
new XamlType(differentCultureType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
false
};
foreach (byte[]? keyToken in new object?[] { null, Array.Empty<byte>(), new byte[] { 183, 122, 92, 86, 25, 52, 224, 138 } })
{
var differentPublicKeyTokenType = new ReflectionOnlyType(typeof(XamlType));
var differentPublicKeyTokenAssemblyName = new AssemblyName(differentPublicKeyTokenType.Assembly.FullName!);
differentPublicKeyTokenAssemblyName.SetPublicKeyToken(keyToken);
differentPublicKeyTokenType.AssemblyDelegator!.FullNameResult = differentPublicKeyTokenAssemblyName.FullName;
yield return new object?[]
{
new XamlType(differentPublicKeyTokenType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
false
};
}
var windowsBaseType = new ReflectionOnlyType(typeof(XamlType));
var windowsBaseAssemblyName = new AssemblyName(windowsBaseType.Assembly.FullName!)
{
Name = "WindowsBase"
};
windowsBaseAssemblyName.SetPublicKeyToken(new byte[] { 49, 191, 56, 86, 173, 54, 78, 53 });
windowsBaseType.AssemblyDelegator!.FullNameResult = windowsBaseAssemblyName.FullName;
yield return new object?[]
{
new XamlType(windowsBaseType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
true
};
var invalidWindowsBaseType = new ReflectionOnlyType(typeof(XamlType));
var invalidWindowsBaseAssemblyName = new AssemblyName(invalidWindowsBaseType.Assembly.FullName!)
{
Name = "BadWindowsBase"
};
invalidWindowsBaseAssemblyName.SetPublicKeyToken(new byte[] { 49, 191, 56, 86, 173, 54, 78, 53 });
invalidWindowsBaseType.AssemblyDelegator!.FullNameResult = invalidWindowsBaseAssemblyName.FullName;
yield return new object?[]
{
new XamlType(invalidWindowsBaseType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
false
};
foreach (byte[]? keyToken in new object?[] { null, Array.Empty<byte>(), new byte[] { 183, 122, 92, 86, 25, 52, 224, 137 } })
{
var invalidKeyTokenWindowsBaseType = new ReflectionOnlyType(typeof(XamlType));
var invalidKeyTokenWindowsBaseAssemblyName = new AssemblyName(invalidKeyTokenWindowsBaseType.Assembly.FullName!)
{
Name = "WindowsBase"
};
invalidKeyTokenWindowsBaseAssemblyName.SetPublicKeyToken(keyToken);
invalidKeyTokenWindowsBaseType.AssemblyDelegator!.FullNameResult = invalidKeyTokenWindowsBaseAssemblyName.FullName;
yield return new object?[]
{
new XamlType(invalidKeyTokenWindowsBaseType, new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
false
};
}
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(int)), new XamlSchemaContext()),
new XamlType(typeof(XamlType), new XamlSchemaContext()),
false
};
// Interfaces
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(CustomNameScope)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(CustomNameScopeDictionary)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlType)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
false
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(int)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
false
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(INameScope)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(INameScope)), new XamlSchemaContext()),
new XamlType(typeof(INameScopeDictionary), new XamlSchemaContext()),
false
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(INameScopeDictionary)), new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
true
};
var nullInterface = new ReflectionOnlyType(typeof(INameScopeDictionary))
{
GetInterfacesResult = new Type?[] { null }
};
yield return new object?[]
{
new XamlType(nullInterface, new XamlSchemaContext()),
new XamlType(typeof(INameScope), new XamlSchemaContext()),
false
};
// Generic type parameter.
Type genericTypeParameter = typeof(XamlValueConverter<>).GetTypeInfo().GenericTypeParameters[0];
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(int)), new XamlSchemaContext()),
new XamlType(genericTypeParameter, new XamlSchemaContext()),
true
};
var nullConstrainedGenericParameter = new ReflectionOnlyType(genericTypeParameter)
{
GetGenericParameterConstraintsResult = new Type?[] { null }
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(int)), new XamlSchemaContext()),
new XamlType(nullConstrainedGenericParameter, new XamlSchemaContext()),
false
};
var constrainedGenericParameter = new ReflectionOnlyType(genericTypeParameter)
{
GetGenericParameterConstraintsResult = new Type[] { typeof(XamlObjectWriterSettings) }
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlObjectWriterSettings)), new XamlSchemaContext()),
new XamlType(constrainedGenericParameter, new XamlSchemaContext()),
true
};
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlWriterSettings)), new XamlSchemaContext()),
new XamlType(constrainedGenericParameter, new XamlSchemaContext()),
false
};
// Edge case - assembly qualified name not equal, then equal
// when checking for subclass.
yield return new object?[]
{
new XamlType(new ReflectionOnlyType(typeof(XamlType)), new XamlSchemaContext()),
new XamlType(new InconsistentNameTypeDelegator(typeof(XamlType)), new XamlSchemaContext()),
false
};
}
[Theory]
[MemberData(nameof(CanAssignTo_TestData))]
public void CanAssignTo_Invoke_ReturnsExpected(XamlType type, XamlType other, bool expected)
{
Assert.Equal(expected, type.CanAssignTo(other));
}
public static IEnumerable<object?[]> Equals_TestData()
{
var type = new XamlType(typeof(int), new XamlSchemaContext());
yield return new object?[] { type, type, true };
yield return new object?[] { type, new XamlType(typeof(int), new XamlSchemaContext()), true };
yield return new object?[] { type, new XamlType(typeof(string), new XamlSchemaContext()), false };
yield return new object?[] { type, new XamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object?[] { type, new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType("namespace", "name", null, new XamlSchemaContext()), true };
yield return new object?[] { new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), true };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType("otherNamespace", "name", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType("namespace", "otherName", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), new XamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(string), new XamlSchemaContext()) }, new XamlSchemaContext()), new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(string), new XamlSchemaContext()) }, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()), new XamlType("namespace", "name", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()), new XamlType(typeof(string), new XamlSchemaContext()) }, new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object?[] { new XamlType("namespace", "name", null, new XamlSchemaContext()), new SubXamlType("name", null, new XamlSchemaContext()), false };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new SubXamlType("name", null, new XamlSchemaContext()), true };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new SubXamlType("otherName", null, new XamlSchemaContext()), false };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new XamlType(typeof(int), new XamlSchemaContext()), false };
yield return new object?[] { new SubXamlType("name", null, new XamlSchemaContext()), new XamlType("namespace", "name", null, new XamlSchemaContext()), false };
yield return new object?[] { type, null, false };
yield return new object?[] { type, new object(), false };
yield return new object?[] { null, type, false };
yield return new object?[] { null, null, true };
}
[Theory]
[MemberData(nameof(Equals_TestData))]
public void Equals_Invoke_ReturnsExpected(XamlType type, object obj, bool expected)
{
XamlType? other = obj as XamlType;
if (type != null)
{
Assert.Equal(expected, type.Equals(obj));
Assert.Equal(expected, type.Equals(other));
}
Assert.Equal(expected, type == other);
Assert.Equal(!expected, type != other);
}
public static IEnumerable<object[]> GetHashCode_TestData()
{
yield return new object[] { new XamlType("name", "namespace", null, new XamlSchemaContext()) };
yield return new object[] { new XamlType("name", "namespace", new XamlType[] { new XamlType(typeof(int), new XamlSchemaContext()) }, new XamlSchemaContext()) };
yield return new object[] { new XamlType(typeof(int), new XamlSchemaContext()) };
yield return new object[] { new SubXamlType("typeName", null, new XamlSchemaContext()) };
yield return new object[] { new NoUnderlyingOrBaseType() };
}
[Theory]
[MemberData(nameof(GetHashCode_TestData))]
public void GetHashCode_Invoke_ReturnsExpected(XamlType type)
{
Assert.Equal(type.GetHashCode(), type.GetHashCode());
}
private static void AssertEqualXamlMembers(XamlMember[]? expected, IEnumerable<XamlMember> actual)
{
if (expected == null)
{
Assert.Null(actual);
return;
}
XamlMember[] sortedActual = actual.OrderBy(m => m.Name).ToArray();
Assert.Equal(expected.Length, sortedActual.Length);
for (int i = 0; i < expected.Length; i++)
{
AssertEqualXamlMember(expected[i], sortedActual[i]);
}
}
private static void AssertEqualXamlMember(XamlMember expected, XamlMember actual)
{
if (expected == null)
{
Assert.Null(actual);
return;
}
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.UnderlyingMember, actual.UnderlyingMember);
Assert.Equal(GetUnderlyingGetter(expected), GetUnderlyingGetter(actual));
Assert.Equal(GetUnderlyingSetter(expected), GetUnderlyingSetter(actual));
}
private class NoUnderlyingOrBaseType : SubXamlType
{
public NoUnderlyingOrBaseType() : base("name", null, new XamlSchemaContext()) { }
protected override bool LookupIsUnknown() => false;
protected override XamlType LookupBaseType() => null!;
}
private class ReflectionOnlyType : CustomType
{
public ReflectionOnlyType(Type delegatingType) : base(delegatingType)
{
AssemblyResult = new CustomAssembly(base.Assembly)
{
ReflectionOnlyResult = true
};
}
public CustomAssembly? AssemblyDelegator
{
get => AssemblyResult.HasValue ? AssemblyResult.Value as CustomAssembly : null;
set => AssemblyResult = value!;
}
}
private class ReflectionOnlyCustomAttributeDataType : CustomType
{
public ReflectionOnlyCustomAttributeDataType(Type delegatingType) : base(delegatingType)
{
}
public override IList<CustomAttributeData> GetCustomAttributesData()
{
IList<CustomAttributeData> baseData = typeImpl.GetCustomAttributesData();
return baseData.Select(c =>
{
return new CustomCustomAttributeData
{
ConstructorResult = new CustomConstructorInfo(c.Constructor)
{
DeclaringTypeResult = new ReflectionOnlyType(c.Constructor.DeclaringType!)
},
ConstructorArgumentsResult = c.ConstructorArguments
};
}).ToArray();
}
}
private class ThrowsCustomAttributeFormatExceptionDelegator : TypeDelegator
{
public ThrowsCustomAttributeFormatExceptionDelegator(Type delegatingType) : base(delegatingType)
{
}
public override IList<CustomAttributeData> GetCustomAttributesData()
{
throw new CustomAttributeFormatException();
}
}
private class NestedClass { }
private class InconsistentNameTypeDelegator : ReflectionOnlyType
{
private bool FullNameCalled { get; set; }
public InconsistentNameTypeDelegator(Type delegatingType) : base(delegatingType)
{
}
public override string FullName
{
get
{
if (FullNameCalled)
{
return base.FullName!;
}
FullNameCalled = true;
return "";
}
}
}
private class CustomAttributeProvider : ICustomAttributeProvider
{
public Func<Type, bool, object[]>? GetCustomAttributesAction { get; set; }
public object[] GetCustomAttributes(Type attributeType, bool inherit)
{
if (GetCustomAttributesAction is null)
{
throw new NotImplementedException();
}
return GetCustomAttributesAction(attributeType, inherit);
}
public object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
public Func<Type, bool, bool>? IsDefinedAction { get; set; }
public bool IsDefined(Type attributeType, bool inherit)
{
if (IsDefinedAction is null)
{
throw new NotImplementedException();
}
return IsDefinedAction(attributeType, inherit);
}
}
private class CustomXamlSchemaContext : XamlSchemaContext
{
public Func<Type, XamlType>? GetXamlTypeAction { get; set; }
public override XamlType GetXamlType(Type type)
{
if (GetXamlTypeAction is null)
{
throw new NotImplementedException();
}
return GetXamlTypeAction(type);
}
}
public class CustomCustomAttributeData : CustomAttributeData
{
public ConstructorInfo? ConstructorResult { get; set; }
public override ConstructorInfo Constructor => ConstructorResult!;
public IList<CustomAttributeTypedArgument>? ConstructorArgumentsResult { get; set; }
public override IList<CustomAttributeTypedArgument> ConstructorArguments => ConstructorArgumentsResult!;
}
}
#pragma warning disable IDE0040, IDE0060 // Add accessibility modifiers, Remove unused parameter
abstract class AbstractClass { }
static class StaticClass { }
class ClassWithDefaultConstructor { }
class ClassWithInternalDefaultConstructor
{
internal ClassWithInternalDefaultConstructor() { }
}
class ClassWithProtectedDefaultConstructor
{
protected ClassWithProtectedDefaultConstructor() { }
}
class ClassWithPrivateDefaultConstructor
{
private ClassWithPrivateDefaultConstructor() { }
}
class ClassWithCustomConstructor
{
public ClassWithCustomConstructor(int i) {}
}
}
class GlobalNamespaceClass
{
}
#pragma warning restore IDE0040, IDE0060 // Add accessibility modifiers, Remove unused parameter
|