Welcome to mirror list, hosted at ThFree Co, Russian Federation.

DependencyGraphTests.cs « tests « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a0a60efda556d0e1d1a0f43edd8acc692de3612a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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.

using System;
using System.Collections.Generic;

using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;

using Xunit;

using CustomAttributeValue = System.Reflection.Metadata.CustomAttributeValue<Internal.TypeSystem.TypeDesc>;

namespace ILCompiler.Compiler.Tests
{
    //
    // This test uses IL scanner to scan a dependency graph, starting with a
    // single method from the test assembly.
    // It then checks various invariants about the resulting dependency graph.
    // The test method declares these invariants using custom attributes.
    //
    // The invariants to check for are:
    // * Whether an EEType was/was not generated
    // * Whether a method body was/was not generated
    // * Etc.
    //
    // The most valuable tests are the ones that check that something was not
    // generated. These let us create unit tests for size on disk regressions.
    //

    public class DependencyGraphTests
    {
        public static IEnumerable<object[]> GetTestMethods()
        {
            var target = new TargetDetails(TargetArchitecture.X64, TargetOS.Windows, TargetAbi.CoreRT);
            var context = new CompilerTypeSystemContext(target, SharedGenericsMode.CanonicalReferenceTypes);

            context.InputFilePaths = new Dictionary<string, string> {
                { "Test.CoreLib", @"Test.CoreLib.dll" },
                { "ILCompiler.Compiler.Tests.Assets", @"ILCompiler.Compiler.Tests.Assets.dll" },
                };
            context.ReferenceFilePaths = new Dictionary<string, string>();

            context.SetSystemModule(context.GetModuleForSimpleName("Test.CoreLib"));
            var testModule = context.GetModuleForSimpleName("ILCompiler.Compiler.Tests.Assets");

            bool foundSomethingToCheck = false;
            foreach (var type in testModule.GetType("ILCompiler.Compiler.Tests.Assets", "DependencyGraph").GetNestedTypes())
            {
                foundSomethingToCheck = true;
                yield return new object[] { type.GetMethod("Entrypoint", null) };
            }

            Assert.True(foundSomethingToCheck, "No methods to check?");
        }

        [Theory]
        [MemberData(nameof(GetTestMethods))]
        public void TestDependencyGraphInvariants(EcmaMethod method)
        {
            //
            // Scan the input method
            //

            var context = (CompilerTypeSystemContext)method.Context;
            CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup();

            CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup);
            IILScanner scanner = builder.GetILScannerBuilder()
                .UseCompilationRoots(new ICompilationRootProvider[] { new SingleMethodRootProvider(method) })
                .ToILScanner();

            ILScanResults results = scanner.Scan();

            //
            // Check invariants
            //

            const string assetsNamespace = "ILCompiler.Compiler.Tests.Assets";
            bool foundSomethingToCheck = false;

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "GeneratesConstructedEETypeAttribute"))
            {
                foundSomethingToCheck = true;
                Assert.Contains((TypeDesc)attr.FixedArguments[0].Value, results.ConstructedEETypes);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "NoConstructedEETypeAttribute"))
            {
                foundSomethingToCheck = true;
                Assert.DoesNotContain((TypeDesc)attr.FixedArguments[0].Value, results.ConstructedEETypes);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "GeneratesMethodBodyAttribute"))
            {
                foundSomethingToCheck = true;
                MethodDesc methodToCheck = GetMethodFromAttribute(attr);
                Assert.Contains(methodToCheck.GetCanonMethodTarget(CanonicalFormKind.Specific), results.CompiledMethodBodies);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "NoMethodBodyAttribute"))
            {
                foundSomethingToCheck = true;
                MethodDesc methodToCheck = GetMethodFromAttribute(attr);
                Assert.DoesNotContain(methodToCheck.GetCanonMethodTarget(CanonicalFormKind.Specific), results.CompiledMethodBodies);
            }

            //
            // Make sure we checked something
            //

            Assert.True(foundSomethingToCheck, "No invariants to check?");
        }

        private static MethodDesc GetMethodFromAttribute(CustomAttributeValue attr)
        {
            if (attr.NamedArguments.Length > 0)
                throw new NotImplementedException(); // TODO: parse sig and instantiation

            return ((TypeDesc)attr.FixedArguments[0].Value).GetMethod((string)attr.FixedArguments[1].Value, null);
        }
    }
}