File: Metadata\WinMdMetadataTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\WinRT\Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.WinRT.UnitTests)
// 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.Text;
 
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
 
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
 
using Xunit;
using Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    // Unit tests for programs that use the Windows.winmd file.
    // 
    // Checks to see that types are forwarded correctly, that 
    // metadata files are loaded as they should, etc.
    public class WinMdMetadataTests : CSharpTestBase
    {
        /// <summary>
        /// Make sure that the members of a function are forwarded to their appropriate types.
        /// We do this by checking that the first parameter of
        /// Windows.UI.Text.ITextRange.SetPoint(Point p...) gets forwarded to the 
        /// System.Runtime.WindowsRuntime assembly.
        /// </summary> 
        [Fact]
        public void FunctionSignatureForwarded()
        {
            var text = "public class A{};";
            var comp = CreateCompilationWithWinRT(text);
 
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
 
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
            wns1 = wns1.GetMember<NamespaceSymbol>("UI");
            wns1 = wns1.GetMember<NamespaceSymbol>("Text");
            var itextrange = wns1.GetMember<PENamedTypeSymbol>("ITextRange");
            var func = itextrange.GetMember<PEMethodSymbol>("SetPoint");
            var pt = ((PEParameterSymbol)(func.Parameters[0])).Type as PENamedTypeSymbol;
            Assert.Equal("System.Runtime.WindowsRuntime", pt.ContainingAssembly.Name);
        }
 
        /// <summary>
        /// Make sure that a delegate defined in Windows.winmd has a public constructor
        /// (by default, all delegates in Windows.winmd have a private constructor).
        /// </summary> 
        [Fact]
        public void DelegateConstructorMarkedPublic()
        {
            var text = "public class A{};";
            var comp = CreateCompilationWithWinRT(text);
 
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
 
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
            wns1 = wns1.GetMember<NamespaceSymbol>("UI");
            wns1 = wns1.GetMember<NamespaceSymbol>("Xaml");
            var itextrange = wns1.GetMember<PENamedTypeSymbol>("SuspendingEventHandler");
            var func = itextrange.GetMember<PEMethodSymbol>(".ctor");
            Assert.Equal(Accessibility.Public, func.DeclaredAccessibility);
        }
 
        /// <summary>
        /// Verify that Windows.Foundation.Uri forwards successfully
        /// to System.Uri
        /// </summary>
        [Fact]
        public void TypeForwardingRenaming()
        {
            var text = "public class A{};";
            var comp = CreateCompilationWithWinRT(text);
 
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
 
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
            wns1 = wns1.GetMember<NamespaceSymbol>("Foundation");
            var iref = wns1.GetMember<PENamedTypeSymbol>("IUriRuntimeClass");
            var func = iref.GetMember<PEMethodSymbol>("CombineUri");
            var ret = func.ReturnTypeWithAnnotations;
            Assert.Equal("System.Uri", func.ReturnType.ToTestDisplayString());
        }
 
        /// <summary>
        /// Verify that WinMd types are marked as private so that the
        /// C# developer cannot instantiate them.
        /// </summary>
        [Fact]
        public void WinMdTypesDefPrivate()
        {
            var text = "public class A{};";
            var comp = CreateCompilationWithWinRT(text);
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
 
            var wns2 = wns1.GetMember<NamespaceSymbol>("Foundation");
            var clas = wns2.GetMember<PENamedTypeSymbol>("Point");
            Assert.Equal(Accessibility.Internal, clas.DeclaredAccessibility);
        }
 
        /// <summary>
        /// Verify that Windows.UI.Colors.Black is forwarded to the
        /// System.Runtime.WindowsRuntime.dll assembly.
        /// </summary>
        [Fact]
        public void WinMdColorType()
        {
            var text = "public class A{};";
 
            var comp = CreateCompilationWithWinRT(text);
 
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
            var wns2 = wns1.GetMember<NamespaceSymbol>("UI");
            var clas = wns2.GetMember<TypeSymbol>("Colors");
            var blk = clas.GetMembers("Black").Single();
            //The windows.winmd module points to a Windows.UI.Color which should be modified to belong
            //to System.Runtime.WindowsRuntime
            Assert.Equal("System.Runtime.WindowsRuntime.dll", ((PENamedTypeSymbol)((((PropertySymbol)(blk)).GetMethod).ReturnType)).ContainingModule.ToString());
        }
 
        /// <summary>
        /// Ensure that a simple program that uses projected types can compile
        /// and run.
        /// </summary>
        [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.TestExecutionNeedsDesktopTypes)]
        public void WinMdColorTest()
        {
            var text = @"using Windows.UI;
                             using Windows.Foundation;
                         
                             public class A{
                                public static void Main(){
                                
                                    var a = Colors.Black;
                                    System.Console.WriteLine(a.ToString());
                                }
                             };";
 
            CompileAndVerify(text, WinRtRefs, targetFramework: TargetFramework.Empty, expectedOutput: "#FF000000");
        }
 
        /// <summary>
        /// Test that the metadata adapter correctly projects IReference to INullable
        /// </summary>
        [Fact]
        public void IReferenceToINullableType()
        {
            var text = "public class A{};";
 
            var comp = CreateCompilationWithWinRT(text);
 
            var winmdlib = comp.ExternalReferences.Where(r => r.Display == "Windows").Single();
            var winmdNS = comp.GetReferencedAssemblySymbol(winmdlib);
            var wns1 = winmdNS.GlobalNamespace.GetMember<NamespaceSymbol>("Windows");
            var wns2 = wns1.GetMember<NamespaceSymbol>("Globalization");
            var wns3 = wns2.GetMember<NamespaceSymbol>("NumberFormatting");
            var clas = wns3.GetMember<TypeSymbol>("DecimalFormatter");
            var puint = clas.GetMembers("ParseUInt").Single();
 
            // The return type of ParseUInt should be Nullable<ulong>, not IReference<ulong>
            Assert.Equal("ulong?",
                ((Microsoft.CodeAnalysis.CSharp.Symbols.ConstructedNamedTypeSymbol)
                (((Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol)puint).ReturnType)).ToString());
        }
 
        /// <summary>
        /// Test that a program projects IReference to INullable.
        /// </summary>
        [Fact]
        public void WinMdIReferenceINullableTest()
        {
            var source =
@"using System;
using Windows.Globalization.NumberFormatting;
 
public class C
{
    public static void Main(string[] args)
    {
        var format = new DecimalFormatter();
        ulong result = format.ParseUInt(""10"") ?? 0;
        Console.WriteLine(result);
        result = format.ParseUInt(""-1"") ?? 0;
        Console.WriteLine(result);
    }
}";
            var verifier = this.CompileAndVerifyOnWin8Only(source,
                expectedOutput: "10\r\n0");
            verifier.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(1169511, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1169511")]
        public void WinMdAssemblyQualifiedType()
        {
            var source =
@"using System;
 
[MyAttribute(typeof(C1))]
public class C
{
    public static void Main(string[] args)
    {
    }
}
 
public class MyAttribute : System.Attribute
{
    public MyAttribute(System.Type type)
    {
    }
}
";
            CompileAndVerify(
                source,
                WinRtRefs.Concat(new[] { AssemblyMetadata.CreateFromImage(TestResources.WinRt.W1).GetReference() }),
                targetFramework: TargetFramework.Empty,
                symbolValidator: m =>
            {
                var module = (PEModuleSymbol)m;
                var c = (PENamedTypeSymbol)module.GlobalNamespace.GetTypeMember("C");
                var attributeHandle = module.Module.MetadataReader.GetCustomAttributes(c.Handle).Single();
                string value;
                module.Module.TryExtractStringValueFromAttribute(attributeHandle, out value);
 
                Assert.Equal("C1, W, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime", value);
            });
        }
    }
}