WinMdTests.cs 16.9 KB
Newer Older
J
Jonathon Marolf 已提交
1 2 3
// 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.
4

T
Tomas Matousek 已提交
5 6 7 8
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
9 10 11
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
T
Tomas Matousek 已提交
12
using Microsoft.CodeAnalysis.CSharp.UnitTests;
13
using Microsoft.CodeAnalysis.ExpressionEvaluator;
T
Tomas Matousek 已提交
14
using Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests;
15
using Microsoft.VisualStudio.Debugger.Evaluation;
16
using Roslyn.Test.PdbUtilities;
17
using Roslyn.Test.Utilities;
18
using Roslyn.Utilities;
19 20
using Xunit;

T
Tomas Matousek 已提交
21
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.UnitTests
22 23 24 25 26 27 28 29
{
    public class WinMdTests : ExpressionCompilerTestBase
    {
        /// <summary>
        /// Handle runtime assemblies rather than Windows.winmd
        /// (compile-time assembly) since those are the assemblies
        /// loaded in the debuggee.
        /// </summary>
J
Jared Parsons 已提交
30
        [WorkItem(981104, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/981104")]
31 32 33 34 35 36 37 38 39 40
        [ConditionalFact(typeof(OSVersionWin8))]
        public void Win8RuntimeAssemblies()
        {
            var source =
@"class C
{
    static void M(Windows.Storage.StorageFolder f, Windows.Foundation.Collections.PropertySet p)
    {
    }
}";
J
Jared Parsons 已提交
41
            var compilation0 = CreateEmptyCompilation(
42 43 44 45
                source,
                options: TestOptions.DebugDll,
                assemblyName: ExpressionCompilerUtilities.GenerateUniqueName(),
                references: WinRtRefs);
46

47 48
            var runtimeAssemblies = ExpressionCompilerTestHelpers.GetRuntimeWinMds("Windows.Storage", "Windows.Foundation.Collections");
            Assert.True(runtimeAssemblies.Length >= 2);
C
CyrusNajmabadi 已提交
49

50
            // no reference to Windows.winmd
51 52 53 54 55 56 57 58
            WithRuntimeInstance(compilation0, new[] { MscorlibRef }.Concat(runtimeAssemblies), runtime =>
            {
                var context = CreateMethodContext(runtime, "C.M");
                string error;
                var testData = new CompilationTestData();
                context.CompileExpression("(p == null) ? f : null", out error, testData);
                Assert.Null(error);
                testData.GetMethodData("<>x.<>m0").VerifyIL(
59 60 61 62 63 64 65 66 67 68
@"{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0005
  IL_0003:  ldnull
  IL_0004:  ret
  IL_0005:  ldarg.0
  IL_0006:  ret
}");
69
            });
70 71 72 73 74 75 76 77 78 79 80 81 82
        }

        [ConditionalFact(typeof(OSVersionWin8))]
        public void Win8RuntimeAssemblies_ExternAlias()
        {
            var source =
@"extern alias X;
class C
{
    static void M(X::Windows.Storage.StorageFolder f)
    {
    }
}";
J
Jared Parsons 已提交
83
            var compilation0 = CreateEmptyCompilation(
84 85 86 87
                source,
                options: TestOptions.DebugDll,
                assemblyName: ExpressionCompilerUtilities.GenerateUniqueName(),
                references: WinRtRefs.Select(r => r.Display == "Windows" ? r.WithAliases(new[] { "X" }) : r));
88

89 90
            var runtimeAssemblies = ExpressionCompilerTestHelpers.GetRuntimeWinMds("Windows.Storage");
            Assert.True(runtimeAssemblies.Length >= 1);
91 92

            // no reference to Windows.winmd
93
            WithRuntimeInstance(compilation0, new[] { MscorlibRef }.Concat(runtimeAssemblies), runtime =>
94 95 96 97 98 99 100
            {
                var context = CreateMethodContext(runtime, "C.M");
                string error;
                var testData = new CompilationTestData();
                context.CompileExpression("X::Windows.Storage.FileProperties.PhotoOrientation.Unspecified", out error, testData);
                Assert.Null(error);
                testData.GetMethodData("<>x.<>m0").VerifyIL(
101 102 103 104 105 106
@"{
  // Code size        2 (0x2)
  .maxstack  1
  IL_0000:  ldc.i4.0
  IL_0001:  ret
}");
107
            });
108 109 110 111 112 113 114 115
        }

        [Fact]
        public void Win8OnWin8()
        {
            CompileTimeAndRuntimeAssemblies(
                ImmutableArray.Create(
                    MscorlibRef,
116 117 118
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.Windows)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
119 120
                ImmutableArray.Create(
                    MscorlibRef,
121 122 123 124
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.WindowsData)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.WindowsStorage)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
125 126 127 128 129 130 131 132 133
                "Windows.Storage");
        }

        [Fact]
        public void Win8OnWin10()
        {
            CompileTimeAndRuntimeAssemblies(
                ImmutableArray.Create(
                    MscorlibRef,
134 135 136
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.Windows)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
137 138
                ImmutableArray.Create(
                    MscorlibRef,
139 140 141 142
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.WindowsData)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.WindowsStorage)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_3(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
143 144 145
                "Windows.Storage");
        }

J
Jared Parsons 已提交
146
        [WorkItem(1108135, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1108135")]
147 148 149 150 151 152
        [Fact]
        public void Win10OnWin10()
        {
            CompileTimeAndRuntimeAssemblies(
                ImmutableArray.Create(
                    MscorlibRef,
153 154 155 156
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.WindowsData)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.WindowsStorage)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
157 158
                ImmutableArray.Create(
                    MscorlibRef,
159 160 161
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.Windows)).GetReference(),
                    AssemblyMetadata.CreateFromImage(ToVersion1_4(TestResources.ExpressionCompiler.LibraryA)).GetReference(),
                    AssemblyMetadata.CreateFromImage(TestResources.ExpressionCompiler.LibraryB).GetReference()),
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
                "Windows");
        }

        private void CompileTimeAndRuntimeAssemblies(
            ImmutableArray<MetadataReference> compileReferences,
            ImmutableArray<MetadataReference> runtimeReferences,
            string storageAssemblyName)
        {
            var source =
@"class C
{
    static void M(LibraryA.A a, LibraryB.B b, Windows.Data.Text.TextSegment t, Windows.Storage.StorageFolder f)
    {
    }
}";
J
Jared Parsons 已提交
177
            var compilation0 = CreateEmptyCompilation(source, compileReferences, TestOptions.DebugDll);
178 179 180 181 182 183 184 185
            WithRuntimeInstance(compilation0, runtimeReferences, runtime =>
            {
                var context = CreateMethodContext(runtime, "C.M");
                string error;
                var testData = new CompilationTestData();
                context.CompileExpression("(object)a ?? (object)b ?? (object)t ?? f", out error, testData);
                Assert.Null(error);
                testData.GetMethodData("<>x.<>m0").VerifyIL(
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
@"{
  // Code size       17 (0x11)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  dup
  IL_0002:  brtrue.s   IL_0010
  IL_0004:  pop
  IL_0005:  ldarg.1
  IL_0006:  dup
  IL_0007:  brtrue.s   IL_0010
  IL_0009:  pop
  IL_000a:  ldarg.2
  IL_000b:  dup
  IL_000c:  brtrue.s   IL_0010
  IL_000e:  pop
  IL_000f:  ldarg.3
  IL_0010:  ret
}");
204 205 206 207 208
                testData = new CompilationTestData();
                var result = context.CompileExpression("default(Windows.Storage.StorageFolder)", out error, testData);
                Assert.Null(error);
                var methodData = testData.GetMethodData("<>x.<>m0");
                methodData.VerifyIL(
209 210 211 212 213 214
@"{
  // Code size        2 (0x2)
  .maxstack  1
  IL_0000:  ldnull
  IL_0001:  ret
}");
V
vsadov 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
                // Check return type is from runtime assembly.
                var assemblyReference = AssemblyMetadata.CreateFromImage(result.Assembly).GetReference();
                var compilation = CSharpCompilation.Create(
                    assemblyName: ExpressionCompilerUtilities.GenerateUniqueName(),
                    references: runtimeReferences.Concat(ImmutableArray.Create<MetadataReference>(assemblyReference)));
                var assembly = ImmutableArray.CreateRange(result.Assembly);
                using (var metadata = ModuleMetadata.CreateFromImage(ImmutableArray.CreateRange(assembly)))
                {
                    var reader = metadata.MetadataReader;
                    var typeDef = reader.GetTypeDef("<>x");
                    var methodHandle = reader.GetMethodDefHandle(typeDef, "<>m0");
                    var module = (PEModuleSymbol)compilation.GetMember("<>x").ContainingModule;
                    var metadataDecoder = new MetadataDecoder(module);
                    SignatureHeader signatureHeader;
                    BadImageFormatException metadataException;
A
AlekseyTs 已提交
230
                    var parameters = metadataDecoder.GetSignatureForMethod(methodHandle, out signatureHeader, out metadataException);
J
Jared Parsons 已提交
231
                    Assert.Equal(5, parameters.Length);
V
vsadov 已提交
232
                    var actualReturnType = parameters[0].Type;
J
Jared Parsons 已提交
233
                    Assert.Equal(TypeKind.Class, actualReturnType.TypeKind); // not error
V
vsadov 已提交
234 235 236 237 238
                    var expectedReturnType = compilation.GetMember("Windows.Storage.StorageFolder");
                    Assert.Equal(expectedReturnType, actualReturnType);
                    Assert.Equal(storageAssemblyName, actualReturnType.ContainingAssembly.Name);
                }
            });
239 240 241 242 243 244
        }

        /// <summary>
        /// Assembly-qualified name containing "ContentType=WindowsRuntime",
        /// and referencing runtime assembly.
        /// </summary>
J
Jared Parsons 已提交
245
        [WorkItem(1116143, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1116143")]
246
        [ConditionalFact(typeof(OSVersionWin8), typeof(IsRelease))] // https://github.com/dotnet/roslyn/issues/25702
247 248 249 250 251 252 253 254 255
        public void AssemblyQualifiedName()
        {
            var source =
@"class C
{
    static void M(Windows.Storage.StorageFolder f, Windows.Foundation.Collections.PropertySet p)
    {
    }
}";
J
Jared Parsons 已提交
256
            var compilation = CreateEmptyCompilation(source, WinRtRefs, TestOptions.DebugDll);
257 258 259
            WithRuntimeInstance(compilation, new[] { MscorlibRef }.Concat(ExpressionCompilerTestHelpers.GetRuntimeWinMds("Windows.Storage", "Windows.Foundation.Collections")), runtime =>
            {
                var context = CreateMethodContext(runtime, "C.M");
260

261 262 263
                var aliases = ImmutableArray.Create(
                    VariableAlias("s", "Windows.Storage.StorageFolder, Windows.Storage, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime"),
                    VariableAlias("d", "Windows.Foundation.DateTime, Windows.Foundation, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime"));
264

265 266 267 268 269 270 271 272 273 274
                string error;
                var testData = new CompilationTestData();
                context.CompileExpression(
                    "(object)s.Attributes ?? d.UniversalTime",
                    DkmEvaluationFlags.TreatAsExpression,
                    aliases,
                    out error,
                    testData);
                testData.GetMethodData("<>x.<>m0").VerifyIL(
    @"{
275 276 277
  // Code size       55 (0x37)
  .maxstack  2
  IL_0000:  ldstr      ""s""
C
Charles Stoner 已提交
278
  IL_0005:  call       ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectByAlias(string)""
279 280 281 282 283 284 285
  IL_000a:  castclass  ""Windows.Storage.StorageFolder""
  IL_000f:  callvirt   ""Windows.Storage.FileAttributes Windows.Storage.StorageFolder.Attributes.get""
  IL_0014:  box        ""Windows.Storage.FileAttributes""
  IL_0019:  dup
  IL_001a:  brtrue.s   IL_0036
  IL_001c:  pop
  IL_001d:  ldstr      ""d""
C
Charles Stoner 已提交
286
  IL_0022:  call       ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectByAlias(string)""
287 288 289 290 291
  IL_0027:  unbox.any  ""Windows.Foundation.DateTime""
  IL_002c:  ldfld      ""long Windows.Foundation.DateTime.UniversalTime""
  IL_0031:  box        ""long""
  IL_0036:  ret
}");
292
            });
293 294
        }

J
Jared Parsons 已提交
295
        [WorkItem(1117084, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1117084")]
A
Andrew Casey 已提交
296
        [Fact]
297 298 299 300 301 302 303 304 305
        public void OtherFrameworkAssembly()
        {
            var source =
@"class C
{
    static void M(Windows.UI.Xaml.FrameworkElement f)
    {
    }
}";
J
Jared Parsons 已提交
306
            var compilation = CreateEmptyCompilation(source, WinRtRefs, TestOptions.DebugDll);
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
            WithRuntimeInstance(compilation, new[] { MscorlibRef }.Concat(ExpressionCompilerTestHelpers.GetRuntimeWinMds("Windows.Foundation", "Windows.UI", "Windows.UI.Xaml")), runtime =>
            {
                var context = CreateMethodContext(runtime, "C.M");
                string error;
                ResultProperties resultProperties;
                ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
                var testData = new CompilationTestData();
                var result = context.CompileExpression(
                    "f.RenderSize",
                    DkmEvaluationFlags.TreatAsExpression,
                    NoAliases,
                    DebuggerDiagnosticFormatter.Instance,
                    out resultProperties,
                    out error,
                    out missingAssemblyIdentities,
                    EnsureEnglishUICulture.PreferredOrNull,
                    testData);
                var expectedAssemblyIdentity = WinRtRefs.Single(r => r.Display == "System.Runtime.WindowsRuntime.dll").GetAssemblyIdentity();
                Assert.Equal(expectedAssemblyIdentity, missingAssemblyIdentities.Single());
            });
327 328
        }

J
Jared Parsons 已提交
329
        [WorkItem(1154988, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1154988")]
330 331 332 333 334 335 336 337 338 339
        [ConditionalFact(typeof(OSVersionWin8))]
        public void WinMdAssemblyReferenceRequiresRedirect()
        {
            var source =
@"class C : Windows.UI.Xaml.Controls.UserControl
{
    static void M(C c)
    {
    }
}";
J
Jared Parsons 已提交
340
            var compilation = CreateEmptyCompilation(source, WinRtRefs, TestOptions.DebugDll);
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
            WithRuntimeInstance(compilation, new[] { MscorlibRef }.Concat(ExpressionCompilerTestHelpers.GetRuntimeWinMds("Windows.UI", "Windows.UI.Xaml")), runtime =>
            {
                string errorMessage;
                var testData = new CompilationTestData();
                ExpressionCompilerTestHelpers.CompileExpressionWithRetry(
                    runtime.Modules.SelectAsArray(m => m.MetadataBlock),
                    "c.Dispatcher",
                    ImmutableArray<Alias>.Empty,
                    (metadataBlocks, _) =>
                    {
                        return CreateMethodContext(runtime, "C.M");
                    },
                    (AssemblyIdentity assembly, out uint size) =>
                    {
                        // Compilation should succeed without retry if we redirect assembly refs correctly.
                        // Throwing so that we don't loop forever (as we did before fix)...
                        throw ExceptionUtilities.Unreachable;
                    },
                    out errorMessage,
                    out testData);
                Assert.Null(errorMessage);
                testData.GetMethodData("<>x.<>m0").VerifyIL(
    @"{
364 365 366 367 368 369
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  callvirt   ""Windows.UI.Core.CoreDispatcher Windows.UI.Xaml.DependencyObject.Dispatcher.get""
  IL_0006:  ret
}");
370
            });
371 372
        }

373 374 375 376 377 378 379 380 381 382 383
        private static byte[] ToVersion1_3(byte[] bytes)
        {
            return ExpressionCompilerTestHelpers.ToVersion1_3(bytes);
        }

        private static byte[] ToVersion1_4(byte[] bytes)
        {
            return ExpressionCompilerTestHelpers.ToVersion1_4(bytes);
        }
    }
}