Repository: dotnet/runtime
File: src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveAssemblyBuilderTests.cs (C#)

Code before:
        [Fact]
        public void PersistedAssemblyBuilder_AssemblyIdentityRoundTrip()
        {
            AssemblyName assemblyName = new AssemblyName("MyIdentityAssembly")
            {
                Flags = AssemblyNameFlags.PublicKey,
                ContentType = AssemblyContentType.WindowsRuntime
            };
#pragma warning disable SYSLIB0037 // Type or member is obsolete
            assemblyName.ProcessorArchitecture = ProcessorArchitecture.X86;
#pragma warning restore SYSLIB0037 // Type or member is obsolete

            byte[] expectedPublicKey = typeof(string).Assembly.GetName().GetPublicKey();
            Assert.NotEmpty(expectedPublicKey);
            assemblyName.SetPublicKey(expectedPublicKey);

            PersistedAssemblyBuilder ab = CreateSimplePersistedAssembly(assemblyName);
            using MemoryStream stream = new MemoryStream();
            ab.Save(stream);

            stream.Position = 0;
            using PEReader peReader = new PEReader(stream);
            MetadataReader metadataReader = peReader.GetMetadataReader();
            AssemblyDefinition assemblyDefinition = metadataReader.GetAssemblyDefinition();

            Assert.Equal((AssemblyFlags)assemblyName.Flags | (AssemblyFlags)((int)assemblyName.ContentType << ContentTypeFlagShift), assemblyDefinition.Flags);
            Assert.True((assemblyDefinition.Flags & AssemblyFlags.PublicKey) != 0);
            Assert.Equal(((int)assemblyName.Flags) & ProcessorArchitectureMask, ((int)assemblyDefinition.Flags) & ProcessorArchitectureMask);
            Assert.Equal(expectedPublicKey, metadataReader.GetBlobBytes(assemblyDefinition.PublicKey));
        }

        [Fact]
        public void PersistedAssemblyBuilder_GenerateMetadataWithEntryPoint()
        {
            PersistedAssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilder(_assemblyName);
            TypeBuilder tb = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
            MethodBuilder mb1 = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]);
            ILGenerator il = mb1.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Ret);
            MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeof(int), null);
            ILGenerator il2 = entryPoint.GetILGenerator();
            il2.Emit(OpCodes.Ldc_I4_S, 10);
            il2.Emit(OpCodes.Ldc_I4_2);
            il2.Emit(OpCodes.Call, mb1);
            il2.Emit(OpCodes.Ret);
            tb.CreateType();

            MetadataBuilder metadataBuilder = ab.GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData);

Review comment (suggestion):
@copilot Covert the assembly name to AseemblyName type to avoid hardcoding encoding details like ContentTypeFlagShift into the test. Use the AseemblyName type properties for the validation instead.

Code after:
        public void PersistedAssemblyBuilder_AssemblyIdentityRoundTrip()
        {
            AssemblyName assemblyName = new AssemblyName("MyIdentityAssembly")
            {
                Flags = AssemblyNameFlags.PublicKey | AssemblyNameFlags.Retargetable,
                Version = new Version(9, 8, 7, 6),
                CultureInfo = new CultureInfo("tr-TR")
            };

            byte[] expectedPublicKey = typeof(string).Assembly.GetName().GetPublicKey();
            Assert.NotEmpty(expectedPublicKey);
            assemblyName.SetPublicKey(expectedPublicKey);

            PersistedAssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilder(assemblyName);
            TypeBuilder typeBuilder = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
            typeBuilder.CreateType();
            using MemoryStream stream = new MemoryStream();
            ab.Save(stream);

            stream.Position = 0;
            using PEReader peReader = new PEReader(stream);
            MetadataReader metadataReader = peReader.GetMetadataReader();
            AssemblyDefinition assemblyDefinition = metadataReader.GetAssemblyDefinition();
            AssemblyName loadedAssemblyName = assemblyDefinition.GetAssemblyNameInfo().ToAssemblyName();

            Assert.Equal(assemblyName.Name, loadedAssemblyName.Name);
            Assert.Equal(assemblyName.Version, loadedAssemblyName.Version);
            Assert.Equal(assemblyName.CultureName, loadedAssemblyName.CultureName);
            Assert.Equal(assemblyName.ContentType, loadedAssemblyName.ContentType);
            Assert.Equal(assemblyName.Flags, loadedAssemblyName.Flags);
            Assert.Equal(expectedPublicKey, loadedAssemblyName.GetPublicKey());
        }

        [Fact]
        public void PersistedAssemblyBuilder_GenerateMetadataWithEntryPoint()
        {
            PersistedAssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilder(_assemblyName);
            TypeBuilder tb = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
            MethodBuilder mb1 = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), [typeof(int), typeof(int)]);
            ILGenerator il = mb1.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Ret);
            MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeof(int), null);
            ILGenerator il2 = entryPoint.GetILGenerator();
            il2.Emit(OpCodes.Ldc_I4_S, 10);
            il2.Emit(OpCodes.Ldc_I4_2);
            il2.Emit(OpCodes.Call, mb1);
            il2.Emit(OpCodes.Ret);
            tb.CreateType();