Enable method signature verification

This updates the CoreClr test infrastructure to include verifying the
metadata signaturse of the emitted code. There is not 100% parity due to
the inability to read custom attribute data on parameters, fields, etc
... But that covers only a small number of test cases.

Destructor tests now passing.
上级 e9a1b34c
......@@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class DestructorTests : EmitMetadataTestBase
{
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void ClassDestructor()
{
var text = @"
......@@ -74,7 +74,7 @@ .maxstack 1
");
}
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
[CompilerTrait(CompilerFeature.ExpressionBody)]
public void ExpressionBodiedClassDestructor()
{
......@@ -128,7 +128,7 @@ .maxstack 1
");
}
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
[CompilerTrait(CompilerFeature.ExpressionBody)]
public void ExpressionBodiedSubClassDestructor()
{
......@@ -209,7 +209,7 @@ .maxstack 1
compVerifier.VerifyDiagnostics();
}
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void SubclassDestructor()
{
var text = @"
......@@ -295,7 +295,7 @@ .maxstack 1
compVerifier.VerifyDiagnostics();
}
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void DestructorOverridesNonDestructor()
{
var text = @"
......@@ -360,7 +360,7 @@ public static void Main()
}
[WorkItem(542828, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542828")]
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void BaseTypeHasNonVirtualFinalize()
{
var text = @"
......@@ -416,7 +416,7 @@ public static void Main()
}
[WorkItem(542828, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542828")]
[Fact]
[ConditionalFact(typeof(DesktopOnly))]
public void GenericBaseTypeHasNonVirtualFinalize()
{
var text = @"
......
......@@ -17,7 +17,7 @@
namespace Roslyn.Test.Utilities
{
public struct ModuleDataId
public readonly struct ModuleDataId
{
public string SimpleName { get; }
public string FullName { get; }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if NETCOREAPP2_0
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
......@@ -95,10 +96,7 @@ public int Execute(string moduleName, string[] args, string expectedOutput)
public ImmutableArray<byte> GetMainPdb() => GetEmitData().MainModulePdb;
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName)
{
throw new NotImplementedException();
}
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName) => GetEmitData().GetMemberSignaturesFromMetadata(fullyQualifiedTypeName, memberName);
public void Verify(Verification verification)
{
......@@ -155,6 +153,11 @@ private sealed class EmitData
internal ImmutableArray<byte> MainModulePdb;
internal ImmutableArray<Diagnostic> Diagnostics;
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName)
{
return LoadContext.GetMemberSignaturesFromMetadata(fullyQualifiedTypeName, memberName, AllModuleData.Select(x => x.Id));
}
}
}
}
......
......@@ -11,6 +11,7 @@
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.Loader;
using System.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
......@@ -80,7 +81,7 @@ private Assembly LoadPlatformAssembly(AssemblyName assemblyName, string assembly
throw;
}
assembly = null;
}
}
return assembly;
}
......@@ -172,6 +173,28 @@ private static bool TryGetAssemblyName(string filePath, out string name)
name = null;
return false;
}
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName, IEnumerable<ModuleDataId> searchModules)
{
try
{
var signatures = new SortedSet<string>();
foreach (var id in searchModules)
{
var name = new AssemblyName(id.FullName);
var assembly = LoadFromAssemblyName(name);
foreach (var signature in MetadataSignatureHelper.GetMemberSignatures(assembly, fullyQualifiedTypeName, memberName))
{
signatures.Add(signature);
}
}
return signatures;
}
catch (Exception ex)
{
throw new Exception($"Error getting signatures {fullyQualifiedTypeName}.{memberName}", ex);
}
}
}
}
#endif
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if NET461 || NET46
#if NET461 || NET46 || NETCOREAPP2_0
using System;
using System.Collections.Generic;
using System.Globalization;
......@@ -9,7 +9,7 @@
using System.Text;
using Roslyn.Utilities;
namespace Roslyn.Test.Utilities.Desktop
namespace Roslyn.Test.Utilities
{
public class MetadataSignatureHelper
{
......@@ -34,11 +34,12 @@ static private void AppendType(Type type, StringBuilder sb, bool showGenericCons
{
if (showGenericConstraints && type.IsGenericParameter)
{
if (type.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) sb.Append("class ");
if (type.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) sb.Append("valuetype ");
if (type.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) sb.Append(".ctor ");
var typeInfo = type.GetTypeInfo();
if (typeInfo.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) sb.Append("class ");
if (typeInfo.GenericParameterAttributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) sb.Append("valuetype ");
if (typeInfo.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint)) sb.Append(".ctor ");
var genericConstraints = type.GetGenericParameterConstraints();
var genericConstraints = typeInfo.GetGenericParameterConstraints();
if (genericConstraints.Length > 0)
{
sb.Append("(");
......@@ -86,7 +87,7 @@ static private void AppendCustomAttributeData(CustomAttributeData attribute, Str
}
foreach (var namedArgument in attribute.NamedArguments)
{
sb.Append(namedArgument.MemberInfo.Name);
sb.Append(namedArgument.MemberName);
AppendValue(namedArgument.TypedValue.Value, sb);
AppendComma(sb);
}
......@@ -96,6 +97,7 @@ static private void AppendCustomAttributeData(CustomAttributeData attribute, Str
static private void AppendParameterInfo(ParameterInfo parameter, StringBuilder sb)
{
#if NET46 || NET461
foreach (var attribute in parameter.GetCustomAttributesData())
{
// these are pseudo-custom attributes that are added by Reflection but don't appear in metadata as custom attributes:
......@@ -108,6 +110,8 @@ static private void AppendParameterInfo(ParameterInfo parameter, StringBuilder s
sb.Append(" ");
}
}
#endif
foreach (var modreq in parameter.GetRequiredCustomModifiers())
{
sb.Append("modreq(");
......@@ -134,11 +138,13 @@ static private void AppendParameterInfo(ParameterInfo parameter, StringBuilder s
sb.Append(" ");
sb.Append(parameter.Name);
#if NET46 || NET461
var defaultValue = parameter.RawDefaultValue;
if (defaultValue != DBNull.Value)
{
AppendValue(defaultValue, sb);
}
#endif
}
}
......@@ -359,11 +365,13 @@ static private void AppendMethodInfo(MethodInfo method, StringBuilder sb)
{
sb.Append(".method");
#if NET46 || NET461
foreach (var attribute in method.GetCustomAttributesData())
{
sb.Append(" ");
AppendCustomAttributeData(attribute, sb);
}
#endif
sb.Append(" ");
AppendMethodAttributes(sb, method.Attributes);
......@@ -399,11 +407,13 @@ static private void AppendConstructorInfo(ConstructorInfo constructor, StringBui
{
sb.Append(".method");
#if NET46 || NET461
foreach (var attribute in constructor.GetCustomAttributesData())
{
sb.Append(" ");
AppendCustomAttributeData(attribute, sb);
}
#endif
sb.Append(" ");
AppendMethodAttributes(sb, constructor.Attributes);
......@@ -451,11 +461,13 @@ static private void AppendPropertyInfo(PropertyInfo property, StringBuilder sb)
{
sb.Append(".property ");
#if NET46 || NET461
foreach (var attribute in property.GetCustomAttributesData())
{
AppendCustomAttributeData(attribute, sb);
sb.Append(" ");
}
#endif
foreach (var modreq in property.GetRequiredCustomModifiers())
{
sb.Append("modreq(");
......@@ -512,11 +524,14 @@ static private void AppendFieldInfo(FieldInfo field, StringBuilder sb)
{
sb.Append(".field ");
#if NET46 || NET461
foreach (var attribute in field.GetCustomAttributesData())
{
AppendCustomAttributeData(attribute, sb);
sb.Append(" ");
}
#endif
foreach (var modreq in field.GetRequiredCustomModifiers())
{
sb.Append("modreq(");
......@@ -539,10 +554,14 @@ static private void AppendFieldInfo(FieldInfo field, StringBuilder sb)
if (field.IsInitOnly) sb.Append("initonly ");
if (field.IsLiteral) sb.Append("literal ");
#if NET46 || NET461
if (field.IsNotSerialized) sb.Append("notserialized ");
#endif
if (field.Attributes.HasFlag(FieldAttributes.SpecialName)) sb.Append("specialname ");
if (field.Attributes.HasFlag(FieldAttributes.RTSpecialName)) sb.Append("rtspecialname ");
#if NET46 || NET461
if (field.IsPinvokeImpl) sb.Append("pinvokeimpl ");
#endif
sb.Append(field.IsStatic ? "static " : "instance ");
AppendType(field.FieldType, sb);
......@@ -559,11 +578,13 @@ static private void AppendEventInfo(EventInfo @event, StringBuilder sb)
{
sb.Append(".event ");
#if NET46 || NET461
foreach (var attribute in @event.GetCustomAttributesData())
{
AppendCustomAttributeData(attribute, sb);
sb.Append(" ");
}
#endif
if (@event.Attributes.HasFlag(EventAttributes.SpecialName)) sb.Append("specialname ");
if (@event.Attributes.HasFlag(EventAttributes.RTSpecialName)) sb.Append("rtspecialname ");
......@@ -572,7 +593,7 @@ static private void AppendEventInfo(EventInfo @event, StringBuilder sb)
sb.Append(" ");
sb.Append(@event.Name);
}
#endregion
#endregion
static public IEnumerable<string> GetMemberSignatures(System.Reflection.Assembly assembly, string fullyQualifiedTypeName)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册