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

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitek Karas <vitek.karas@microsoft.com>2019-12-19 16:25:32 +0300
committerMarek Safar <marek.safar@gmail.com>2019-12-19 16:25:32 +0300
commit58907e37dde42af0066899d64694223914a2287a (patch)
tree3385d00d5438cfaff219c90b508339d7cd897f4c /test/Mono.Linker.Tests
parent08ef96864a817c5e6579bdf19a72a8287b3ee917 (diff)
Add abstraction between the linker and the dependency tracing/re… (#872)
* Add abstraction between the linker and the dependency tracing/recording. Adds IDependencyRecorder which separates the linker/tracer from the actual implementation which stores the dependencies. Implements the default XML writer for the dependencies (should produce exactly the same output as before the change). Adds test infra to test the dependency recorder directly (as a test mock) and a simple test. Motivation: Future analyzers need to have visibility into the dependency analysis (MarkStep basically) to report what caused a given method/type to be included. We already expose this information through the dependency XML, this just adds an API to do this programatically. * PR feedback Use GetDefaultContext for context customization (made it instance call - virtual). Remove any default tracer logic from Tracer and use XmlDependencyRecorder directly in places where we want XML output. * Fix build break on Mono
Diffstat (limited to 'test/Mono.Linker.Tests')
-rw-r--r--test/Mono.Linker.Tests/TestCases/IndividualTests.cs4
-rw-r--r--test/Mono.Linker.Tests/TestCases/TestDatabase.cs5
-rw-r--r--test/Mono.Linker.Tests/TestCases/TestSuites.cs6
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs4
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerCustomizations.cs20
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs21
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs43
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs11
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestDependencyRecorder.cs25
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs15
10 files changed, 146 insertions, 8 deletions
diff --git a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs
index 0a13697e0..6a7ae9c56 100644
--- a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs
+++ b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs
@@ -1,12 +1,10 @@
using System;
-using System.IO;
using System.Xml;
using Mono.Cecil;
using Mono.Linker.Tests.Cases.CommandLine.Mvid;
using Mono.Linker.Tests.Cases.References.Individual;
using Mono.Linker.Tests.Cases.Tracing.Individual;
using Mono.Linker.Tests.Extensions;
-using Mono.Linker.Tests.TestCases;
using Mono.Linker.Tests.TestCasesRunner;
using NUnit.Framework;
@@ -34,7 +32,7 @@ namespace Mono.Linker.Tests.TestCases
var testcase = CreateIndividualCase (typeof (CanEnableDependenciesDump));
var result = Run (testcase);
- var outputPath = result.OutputAssemblyPath.Parent.Combine (Tracer.DefaultDependenciesFileName);
+ var outputPath = result.OutputAssemblyPath.Parent.Combine (XmlDependencyRecorder.DefaultDependenciesFileName);
if (!outputPath.Exists ())
Assert.Fail ($"The dependency dump file is missing. Expected it to exist at {outputPath}");
}
diff --git a/test/Mono.Linker.Tests/TestCases/TestDatabase.cs b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs
index 726516d21..b29dd2d43 100644
--- a/test/Mono.Linker.Tests/TestCases/TestDatabase.cs
+++ b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs
@@ -151,6 +151,11 @@ namespace Mono.Linker.Tests.TestCases
return NUnitCasesBySuiteName ("Substitutions");
}
+ public static IEnumerable<TestCaseData> TracingTests ()
+ {
+ return NUnitCasesBySuiteName ("Tracing");
+ }
+
public static TestCaseCollector CreateCollector ()
{
string rootSourceDirectory;
diff --git a/test/Mono.Linker.Tests/TestCases/TestSuites.cs b/test/Mono.Linker.Tests/TestCases/TestSuites.cs
index c7d906c36..2fda3c3e9 100644
--- a/test/Mono.Linker.Tests/TestCases/TestSuites.cs
+++ b/test/Mono.Linker.Tests/TestCases/TestSuites.cs
@@ -181,6 +181,12 @@ namespace Mono.Linker.Tests.TestCases
Run (testCase);
}
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.TracingTests))]
+ public void TracingTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
protected virtual void Run (TestCase testCase)
{
var runner = new TestRunner (new ObjectFactory ());
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs
index b62419fd6..75436912f 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs
@@ -11,8 +11,9 @@ namespace Mono.Linker.Tests.TestCasesRunner {
public readonly TestCaseMetadaProvider MetadataProvider;
public readonly ManagedCompilationResult CompilationResult;
public readonly LinkerTestLogger Logger;
+ public readonly LinkerCustomizations Customizations;
- public LinkedTestCaseResult (TestCase testCase, NPath inputAssemblyPath, NPath outputAssemblyPath, NPath expectationsAssemblyPath, TestCaseSandbox sandbox, TestCaseMetadaProvider metadaProvider, ManagedCompilationResult compilationResult, LinkerTestLogger logger)
+ public LinkedTestCaseResult (TestCase testCase, NPath inputAssemblyPath, NPath outputAssemblyPath, NPath expectationsAssemblyPath, TestCaseSandbox sandbox, TestCaseMetadaProvider metadaProvider, ManagedCompilationResult compilationResult, LinkerTestLogger logger, LinkerCustomizations customizations)
{
TestCase = testCase;
InputAssemblyPath = inputAssemblyPath;
@@ -22,6 +23,7 @@ namespace Mono.Linker.Tests.TestCasesRunner {
MetadataProvider = metadaProvider;
CompilationResult = compilationResult;
Logger = logger;
+ Customizations = customizations;
}
}
} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerCustomizations.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerCustomizations.cs
new file mode 100644
index 000000000..d0b65edec
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerCustomizations.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Mono.Linker.Tests.TestCasesRunner
+{
+ /// <summary>
+ /// Stores various customizations which can be added to the linker at runtime,
+ /// for example test implementations of certain interfaces.
+ /// </summary>
+ public class LinkerCustomizations
+ {
+ public TestDependencyRecorder DependencyRecorder { get; set; }
+
+ public event Action<LinkContext> CustomizeContext;
+
+ public void CustomizeLinkContext(LinkContext context)
+ {
+ CustomizeContext?.Invoke (context);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
index 12d15bcb4..eb9a78a50 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
@@ -1,8 +1,25 @@
namespace Mono.Linker.Tests.TestCasesRunner {
public class LinkerDriver {
- public virtual void Link (string [] args, ILogger logger)
+ protected class TestDriver : Driver
{
- new Driver (args).Run (logger);
+ LinkerCustomizations _customization;
+
+ public TestDriver(string[] args, LinkerCustomizations customizations) : base(args)
+ {
+ _customization = customizations;
+ }
+
+ protected override LinkContext GetDefaultContext (Pipeline pipeline)
+ {
+ LinkContext context = base.GetDefaultContext (pipeline);
+ _customization.CustomizeLinkContext (context);
+ return context;
+ }
+ }
+
+ public virtual void Link (string [] args, LinkerCustomizations customizations, ILogger logger)
+ {
+ new TestDriver (args, customizations).Run (logger);
}
}
} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
index 02814196c..f2cf4efd1 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
@@ -167,6 +167,7 @@ namespace Mono.Linker.Tests.TestCasesRunner {
protected virtual void AdditionalChecking (LinkedTestCaseResult linkResult, AssemblyDefinition original, AssemblyDefinition linked)
{
VerifyLoggedMessages(original, linkResult.Logger);
+ VerifyRecordedDependencies (original, linkResult.Customizations.DependencyRecorder);
}
protected virtual void InitialChecking (LinkedTestCaseResult linkResult, AssemblyDefinition original, AssemblyDefinition linked)
@@ -613,6 +614,48 @@ namespace Mono.Linker.Tests.TestCasesRunner {
}
}
+ void VerifyRecordedDependencies (AssemblyDefinition original, TestDependencyRecorder dependencyRecorder)
+ {
+ foreach (var typeWithRemoveInAssembly in original.AllDefinedTypes ()) {
+ foreach (var attr in typeWithRemoveInAssembly.CustomAttributes) {
+ if (attr.AttributeType.Resolve ().Name == nameof (DependencyRecordedAttribute)) {
+ var expectedSource = (string)attr.ConstructorArguments [0].Value;
+ var expectedTarget = (string)attr.ConstructorArguments [1].Value;
+ var expectedMarked = (string)attr.ConstructorArguments [2].Value;
+
+ if (!dependencyRecorder.Dependencies.Any (dependency => {
+ if (dependency.Source != expectedSource)
+ return false;
+
+ if (dependency.Target != expectedTarget)
+ return false;
+
+ return expectedMarked == null || dependency.Marked.ToString () == expectedMarked;
+ })) {
+
+ string targetCandidates = string.Join(Environment.NewLine, dependencyRecorder.Dependencies
+ .Where (d => d.Target.ToLowerInvariant().Contains (expectedTarget.ToLowerInvariant()))
+ .Select (d => "\t" + DependencyToString (d)));
+ string sourceCandidates = string.Join (Environment.NewLine, dependencyRecorder.Dependencies
+ .Where (d => d.Source.ToLowerInvariant().Contains (expectedSource.ToLowerInvariant()))
+ .Select (d => "\t" + DependencyToString (d)));
+
+ Assert.Fail (
+ $"Expected to find recorded dependency '{expectedSource} -> {expectedTarget} {expectedMarked ?? string.Empty}'{Environment.NewLine}" +
+ $"Potential dependencies matching the target: {Environment.NewLine}{targetCandidates}{Environment.NewLine}" +
+ $"Potential dependencies matching the source: {Environment.NewLine}{sourceCandidates}{Environment.NewLine}" +
+ $"If there's no matches, try to specify just a part of the source/target name and rerun the test.");
+ }
+ }
+ }
+ }
+
+ string DependencyToString(TestDependencyRecorder.Dependency dependency)
+ {
+ return $"{dependency.Source} -> {dependency.Target} Marked: {dependency.Marked}";
+ }
+ }
+
protected TypeDefinition GetOriginalTypeFromInAssemblyAttribute (CustomAttribute inAssemblyAttribute)
{
return GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute.ConstructorArguments [0].Value.ToString (), inAssemblyAttribute.ConstructorArguments [1].Value);
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs
index 1b2383a5f..d7a1d983d 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs
@@ -66,6 +66,17 @@ namespace Mono.Linker.Tests.TestCasesRunner {
return tclo;
}
+ public virtual void CustomizeLinker (LinkerDriver linker, LinkerCustomizations customizations)
+ {
+ if (_testCaseTypeDefinition.CustomAttributes.Any (attr =>
+ attr.AttributeType.Name == nameof (DependencyRecordedAttribute))) {
+ customizations.DependencyRecorder = new TestDependencyRecorder ();
+ customizations.CustomizeContext += context => {
+ context.Tracer.AddRecorder (customizations.DependencyRecorder);
+ };
+ }
+ }
+
#if NETCOREAPP
public static IEnumerable<string> GetTrustedPlatformAssemblies ()
{
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestDependencyRecorder.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestDependencyRecorder.cs
new file mode 100644
index 000000000..8df724fda
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestDependencyRecorder.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Mono.Linker.Tests.TestCasesRunner
+{
+ public class TestDependencyRecorder : IDependencyRecorder
+ {
+ public struct Dependency
+ {
+ public string Source;
+ public string Target;
+ public bool Marked;
+ }
+
+ public List<Dependency> Dependencies = new List<Dependency> ();
+
+ public void RecordDependency (object source, object target, bool marked)
+ {
+ Dependencies.Add (new Dependency () {
+ Source = source.ToString (),
+ Target = target.ToString (),
+ Marked = marked
+ });
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs
index 9fbec7c1e..4d16a83bf 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs
@@ -92,14 +92,16 @@ namespace Mono.Linker.Tests.TestCasesRunner {
private LinkedTestCaseResult Link (TestCase testCase, TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, TestCaseMetadaProvider metadataProvider)
{
var linker = _factory.CreateLinker ();
+ var linkerCustomizations = CustomizeLinker (linker, metadataProvider);
+
var builder = _factory.CreateLinkerArgumentBuilder (metadataProvider);
AddLinkOptions (sandbox, compilationResult, builder, metadataProvider);
LinkerTestLogger logger = new LinkerTestLogger();
- linker.Link (builder.ToArgs (), logger);
+ linker.Link (builder.ToArgs (), linkerCustomizations, logger);
- return new LinkedTestCaseResult (testCase, compilationResult.InputAssemblyPath, sandbox.OutputDirectory.Combine (compilationResult.InputAssemblyPath.FileName), compilationResult.ExpectationsAssemblyPath, sandbox, metadataProvider, compilationResult, logger);
+ return new LinkedTestCaseResult (testCase, compilationResult.InputAssemblyPath, sandbox.OutputDirectory.Combine (compilationResult.InputAssemblyPath.FileName), compilationResult.ExpectationsAssemblyPath, sandbox, metadataProvider, compilationResult, logger, linkerCustomizations);
}
protected virtual void AddLinkOptions (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, LinkerArgumentBuilder builder, TestCaseMetadaProvider metadataProvider)
@@ -122,6 +124,15 @@ namespace Mono.Linker.Tests.TestCasesRunner {
builder.ProcessTestInputAssembly (compilationResult.InputAssemblyPath);
}
+ protected virtual LinkerCustomizations CustomizeLinker(LinkerDriver linker, TestCaseMetadaProvider metadataProvider)
+ {
+ LinkerCustomizations customizations = new LinkerCustomizations ();
+
+ metadataProvider.CustomizeLinker (linker, customizations);
+
+ return customizations;
+ }
+
private T GetResultOfTaskThatMakesNUnitAssertions<T> (Task<T> task)
{
try {