/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Test/Core/Metadata/MetadataValidation.cs
196 строк
8 KB
Jason Malinowski
Switch code that was using Assert.True/False as a replacement for .Fail
21 апр 2026, 23:28
21 апр 2026, 23:28
3bf59ba
Код
Авторство
О чём код?
// 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. #nullable disable using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using Microsoft.CodeAnalysis; using Microsoft.Metadata.Tools; using Roslyn.Utilities; using Xunit; namespace Roslyn.Test.Utilities { public static class MetadataValidation { /// <summary> /// Returns the name of the attribute class /// </summary> internal static string GetAttributeName(MetadataReader metadataReader, CustomAttributeHandle customAttribute) { var ctorHandle = metadataReader.GetCustomAttribute(customAttribute).Constructor; if (ctorHandle.Kind == HandleKind.MemberReference) // MemberRef { var container = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = metadataReader.GetTypeReference((TypeReferenceHandle)container).Name; return metadataReader.GetString(name); } else if (ctorHandle.Kind == HandleKind.MethodDefinition) { var container = metadataReader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle).GetDeclaringType(); var name = metadataReader.GetTypeDefinition(container).Name; return metadataReader.GetString(name); } else { Assert.Fail("not impl"); return null; } } internal static CustomAttributeHandle FindCustomAttribute(MetadataReader metadataReader, string attributeClassName) { foreach (var caHandle in metadataReader.CustomAttributes) { if (string.Equals(GetAttributeName(metadataReader, caHandle), attributeClassName, StringComparison.Ordinal)) { return caHandle; } } return default(CustomAttributeHandle); } /// <summary> /// Used to validate metadata blobs emitted for MarshalAs. /// </summary> internal static void MarshalAsMetadataValidator(PEAssembly assembly, Func<string, PEAssembly, byte[]> getExpectedBlob, bool isField = true) { var metadataReader = assembly.GetMetadataReader(); // no custom attributes should be emitted on parameters, fields or methods: foreach (var ca in metadataReader.CustomAttributes) { Assert.NotEqual("MarshalAsAttribute", GetAttributeName(metadataReader, ca)); } int expectedMarshalCount = 0; if (isField) { // fields foreach (var fieldDef in metadataReader.FieldDefinitions) { var field = metadataReader.GetFieldDefinition(fieldDef); string fieldName = metadataReader.GetString(field.Name); byte[] expectedBlob = getExpectedBlob(fieldName, assembly); if (expectedBlob != null) { BlobHandle descriptor = metadataReader.GetFieldDefinition(fieldDef).GetMarshallingDescriptor(); Assert.False(descriptor.IsNil, "Expecting record in FieldMarshal table"); Assert.NotEqual(0, (int)(field.Attributes & FieldAttributes.HasFieldMarshal)); expectedMarshalCount++; byte[] actualBlob = metadataReader.GetBlobBytes(descriptor); AssertEx.Equal(expectedBlob, actualBlob); } else { Assert.Equal(0, (int)(field.Attributes & FieldAttributes.HasFieldMarshal)); } } } else { // parameters foreach (var methodHandle in metadataReader.MethodDefinitions) { var methodDef = metadataReader.GetMethodDefinition(methodHandle); string memberName = metadataReader.GetString(methodDef.Name); foreach (var paramHandle in methodDef.GetParameters()) { var paramRow = metadataReader.GetParameter(paramHandle); string paramName = metadataReader.GetString(paramRow.Name); byte[] expectedBlob = getExpectedBlob(memberName + ":" + paramName, assembly); if (expectedBlob != null) { Assert.NotEqual(0, (int)(paramRow.Attributes & ParameterAttributes.HasFieldMarshal)); expectedMarshalCount++; BlobHandle descriptor = metadataReader.GetParameter(paramHandle).GetMarshallingDescriptor(); Assert.False(descriptor.IsNil, "Expecting record in FieldMarshal table"); byte[] actualBlob = metadataReader.GetBlobBytes(descriptor); AssertEx.Equal(expectedBlob, actualBlob); } else { Assert.Equal(0, (int)(paramRow.Attributes & ParameterAttributes.HasFieldMarshal)); } } } } Assert.Equal(expectedMarshalCount, metadataReader.GetTableRowCount(TableIndex.FieldMarshal)); } internal static IEnumerable<string> GetFullTypeNames(MetadataReader metadataReader) { foreach (var typeDefHandle in metadataReader.TypeDefinitions) { var typeDef = metadataReader.GetTypeDefinition(typeDefHandle); var ns = metadataReader.GetString(typeDef.Namespace); var name = metadataReader.GetString(typeDef.Name); yield return (ns.Length == 0) ? name : (ns + "." + name); } } internal static IEnumerable<string> GetExportedTypesFullNames(MetadataReader metadataReader) { foreach (var typeDefHandle in metadataReader.ExportedTypes) { var typeDef = metadataReader.GetExportedType(typeDefHandle); var ns = metadataReader.GetString(typeDef.Namespace); var name = metadataReader.GetString(typeDef.Name); yield return (ns.Length == 0) ? name : (ns + "." + name); } } public static void VerifyMetadataEqualModuloMvid(Stream peStream1, Stream peStream2) { peStream1.Position = 0; peStream2.Position = 0; var peReader1 = new PEReader(peStream1); var peReader2 = new PEReader(peStream2); var md1 = peReader1.GetMetadata().GetContent(); var md2 = peReader2.GetMetadata().GetContent(); var mdReader1 = peReader1.GetMetadataReader(); var mdReader2 = peReader2.GetMetadataReader(); var mvidIndex1 = mdReader1.GetModuleDefinition().Mvid; var mvidIndex2 = mdReader2.GetModuleDefinition().Mvid; var mvidOffset1 = mdReader1.GetHeapMetadataOffset(HeapIndex.Guid) + 16 * (MetadataTokens.GetHeapOffset(mvidIndex1) - 1); var mvidOffset2 = mdReader2.GetHeapMetadataOffset(HeapIndex.Guid) + 16 * (MetadataTokens.GetHeapOffset(mvidIndex2) - 1); if (!md1.RemoveRange(mvidOffset1, 16).SequenceEqual(md1.RemoveRange(mvidOffset2, 16))) { var mdw1 = new StringWriter(); var mdw2 = new StringWriter(); new MetadataVisualizer(mdReader1, mdw1).Visualize(); new MetadataVisualizer(mdReader2, mdw2).Visualize(); mdw1.Flush(); mdw2.Flush(); AssertEx.AssertResultsEqual(mdw1.ToString(), mdw2.ToString()); } } } }