diff --git a/src/Basic.CompilerLog.UnitTests/AppDomainUtils.cs b/src/Basic.CompilerLog.UnitTests/AppDomainUtils.cs
new file mode 100644
index 0000000..b2ccc0a
--- /dev/null
+++ b/src/Basic.CompilerLog.UnitTests/AppDomainUtils.cs
@@ -0,0 +1,98 @@
+#if NETFRAMEWORK
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit.Abstractions;
+
+namespace Basic.CompilerLog.UnitTests;
+
+public static class AppDomainUtils
+{
+ private static readonly object s_lock = new object();
+ private static bool s_hookedResolve;
+
+ public static AppDomain Create(string? name = null, string? basePath = null)
+ {
+ name = name ?? "Custom AppDomain";
+ basePath = basePath ?? Path.GetDirectoryName(typeof(AppDomainUtils).Assembly.Location);
+
+ lock (s_lock)
+ {
+ if (!s_hookedResolve)
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += OnResolve;
+ s_hookedResolve = true;
+ }
+ }
+
+ return AppDomain.CreateDomain(name, null, new AppDomainSetup()
+ {
+ ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
+ ApplicationBase = basePath
+ });
+ }
+
+ ///
+ /// When run under xunit without AppDomains all DLLs get loaded via the AssemblyResolve
+ /// event. In some cases the xunit, AppDomain marshalling, xunit doesn't fully hook
+ /// the event and we need to do it for our assemblies.
+ ///
+ private static Assembly? OnResolve(object sender, ResolveEventArgs e)
+ {
+ var assemblyName = new AssemblyName(e.Name);
+ var fullPath = Path.Combine(
+ Path.GetDirectoryName(typeof(AppDomainUtils).Assembly.Location),
+ assemblyName.Name + ".dll");
+ if (File.Exists(fullPath))
+ {
+ return Assembly.LoadFrom(fullPath);
+ }
+
+ return null;
+ }
+}
+
+public sealed class AppDomainTestOutputHelper : MarshalByRefObject, ITestOutputHelper
+{
+ public ITestOutputHelper TestOutputHelper { get; }
+
+ public AppDomainTestOutputHelper(ITestOutputHelper testOutputHelper)
+ {
+ TestOutputHelper = testOutputHelper;
+ }
+
+ public void WriteLine(string message) =>
+ TestOutputHelper.WriteLine(message);
+
+ public void WriteLine(string format, params object[] args) =>
+ TestOutputHelper.WriteLine(format, args);
+}
+
+public sealed class InvokeUtil : MarshalByRefObject
+{
+ internal void Invoke(string typeName, string methodName, ITestOutputHelper testOutputHelper, T state)
+ {
+ var type = typeof(AppDomainUtils).Assembly.GetType(typeName, throwOnError: false)!;
+ var member = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)!;
+
+ // A static lambda will still be an instance method so we need to create the closure
+ // here.
+ var obj = member.IsStatic
+ ? null
+ : type.Assembly.CreateInstance(typeName);
+
+ try
+ {
+ member.Invoke(obj, [testOutputHelper, state]);
+ }
+ catch (TargetInvocationException ex)
+ {
+ throw new Exception(ex.InnerException.Message);
+ }
+ }
+}
+
+#endif
diff --git a/src/Basic.CompilerLog.UnitTests/BinaryLogReaderTests.cs b/src/Basic.CompilerLog.UnitTests/BinaryLogReaderTests.cs
index 87baf50..4557eaa 100644
--- a/src/Basic.CompilerLog.UnitTests/BinaryLogReaderTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/BinaryLogReaderTests.cs
@@ -137,12 +137,15 @@ public void VerifyBasicAnalyzerKind(BasicAnalyzerKind basicAnalyzerKind)
[MemberData(nameof(GetSupportedBasicAnalyzerKinds))]
public void GetCompilationSimple(BasicAnalyzerKind basicAnalyzerKind)
{
- using var reader = BinaryLogReader.Create(Fixture.Console.Value.BinaryLogPath!, basicAnalyzerKind);
- var compilerCall = reader.ReadAllCompilerCalls().First();
- var compilationData = reader.ReadCompilationData(compilerCall);
- Assert.NotNull(compilationData);
- var emitResult = compilationData.EmitToMemory();
- Assert.True(emitResult.Success);
+ RunInContext((FilePath: Fixture.Console.Value.BinaryLogPath!, Kind: basicAnalyzerKind), static (testOutptuHelper, state) =>
+ {
+ using var reader = BinaryLogReader.Create(state.FilePath, state.Kind);
+ var compilerCall = reader.ReadAllCompilerCalls().First();
+ var compilationData = reader.ReadCompilationData(compilerCall);
+ Assert.NotNull(compilationData);
+ var emitResult = compilationData.EmitToMemory();
+ Assert.True(emitResult.Success);
+ });
}
[Fact]
diff --git a/src/Basic.CompilerLog.UnitTests/CodeAnalysisExtensionTests.cs b/src/Basic.CompilerLog.UnitTests/CodeAnalysisExtensionTests.cs
index 6f40e51..e00dbff 100644
--- a/src/Basic.CompilerLog.UnitTests/CodeAnalysisExtensionTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/CodeAnalysisExtensionTests.cs
@@ -20,7 +20,7 @@ public CodeAnalysisExtensionsTests(ITestOutputHelper testOutputHelper, CompilerL
[Fact]
public void EmitToMemory()
{
- var data = GetCompilationData(Fixture.ClassLib.Value.CompilerLogPath);
+ var data = GetCompilationData(Fixture.ClassLib.Value.CompilerLogPath, basicAnalyzerKind: BasicAnalyzerKind.None);
var compilation = data.GetCompilationAfterGenerators();
var result = compilation.EmitToMemory(EmitFlags.Default);
AssertEx.Success(TestOutputHelper, result);
diff --git a/src/Basic.CompilerLog.UnitTests/CompilationDataTests.cs b/src/Basic.CompilerLog.UnitTests/CompilationDataTests.cs
index 6b05582..0d070bb 100644
--- a/src/Basic.CompilerLog.UnitTests/CompilationDataTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/CompilationDataTests.cs
@@ -20,60 +20,69 @@ public CompilationDataTests(ITestOutputHelper testOutputHelper, CompilerLogFixtu
[Fact]
public void EmitToMemoryCombinations()
{
- using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath);
- var data = reader.ReadCompilationData(0);
-
- var emitResult = data.EmitToMemory();
- Assert.True(emitResult.Success);
- AssertEx.HasData(emitResult.AssemblyStream);
- AssertEx.HasData(emitResult.PdbStream);
- Assert.Null(emitResult.XmlStream);
- AssertEx.HasData(emitResult.MetadataStream);
-
- emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream);
- Assert.True(emitResult.Success);
- AssertEx.HasData(emitResult.AssemblyStream);
- AssertEx.HasData(emitResult.PdbStream);
- Assert.Null(emitResult.XmlStream);
- Assert.Null(emitResult.MetadataStream);
-
- emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream | EmitFlags.IncludeXmlStream);
- Assert.True(emitResult.Success);
- AssertEx.HasData(emitResult.AssemblyStream);
- AssertEx.HasData(emitResult.PdbStream);
- AssertEx.HasData(emitResult.XmlStream);
- Assert.Null(emitResult.MetadataStream);
-
- emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream | EmitFlags.IncludeXmlStream | EmitFlags.IncludeMetadataStream);
- Assert.True(emitResult.Success);
- AssertEx.HasData(emitResult.AssemblyStream);
- AssertEx.HasData(emitResult.PdbStream);
- AssertEx.HasData(emitResult.XmlStream);
- AssertEx.HasData(emitResult.MetadataStream);
-
- emitResult = data.EmitToMemory(EmitFlags.MetadataOnly);
- Assert.True(emitResult.Success);
- AssertEx.HasData(emitResult.AssemblyStream);
- Assert.Null(emitResult.PdbStream);
- Assert.Null(emitResult.XmlStream);
- Assert.Null(emitResult.MetadataStream);
+ RunInContext(Fixture.ClassLib.Value.CompilerLogPath, static (testOutputHelper, filePath) =>
+ {
+ using var reader = CompilerLogReader.Create(filePath);
+ var data = reader.ReadCompilationData(0);
+
+ var emitResult = data.EmitToMemory();
+ Assert.True(emitResult.Success);
+ AssertEx.HasData(emitResult.AssemblyStream);
+ AssertEx.HasData(emitResult.PdbStream);
+ Assert.Null(emitResult.XmlStream);
+ AssertEx.HasData(emitResult.MetadataStream);
+
+ emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream);
+ Assert.True(emitResult.Success);
+ AssertEx.HasData(emitResult.AssemblyStream);
+ AssertEx.HasData(emitResult.PdbStream);
+ Assert.Null(emitResult.XmlStream);
+ Assert.Null(emitResult.MetadataStream);
+
+ emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream | EmitFlags.IncludeXmlStream);
+ Assert.True(emitResult.Success);
+ AssertEx.HasData(emitResult.AssemblyStream);
+ AssertEx.HasData(emitResult.PdbStream);
+ AssertEx.HasData(emitResult.XmlStream);
+ Assert.Null(emitResult.MetadataStream);
+
+ emitResult = data.EmitToMemory(EmitFlags.IncludePdbStream | EmitFlags.IncludeXmlStream | EmitFlags.IncludeMetadataStream);
+ Assert.True(emitResult.Success);
+ AssertEx.HasData(emitResult.AssemblyStream);
+ AssertEx.HasData(emitResult.PdbStream);
+ AssertEx.HasData(emitResult.XmlStream);
+ AssertEx.HasData(emitResult.MetadataStream);
+
+ emitResult = data.EmitToMemory(EmitFlags.MetadataOnly);
+ Assert.True(emitResult.Success);
+ AssertEx.HasData(emitResult.AssemblyStream);
+ Assert.Null(emitResult.PdbStream);
+ Assert.Null(emitResult.XmlStream);
+ Assert.Null(emitResult.MetadataStream);
+ });
}
[Fact]
public void EmitToMemoryRefOnly()
{
- using var reader = CompilerLogReader.Create(Fixture.ClassLibRefOnly.Value.CompilerLogPath);
- var data = reader.ReadCompilationData(0);
- var result = data.EmitToMemory();
- Assert.True(result.Success);
+ RunInContext(Fixture.ClassLibRefOnly.Value.CompilerLogPath, static (testOutputHelper, filePath) =>
+ {
+ using var reader = CompilerLogReader.Create(filePath);
+ var data = reader.ReadCompilationData(0);
+ var result = data.EmitToMemory();
+ Assert.True(result.Success);
+ });
}
[Fact]
public void GetAnalyzersNormal()
{
- using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath);
- var data = reader.ReadCompilationData(0);
- Assert.NotEmpty(data.GetAnalyzers());
+ RunInContext(Fixture.ClassLib.Value.CompilerLogPath, static (testOtputHelper, filePath) =>
+ {
+ using var reader = CompilerLogReader.Create(filePath);
+ var data = reader.ReadCompilationData(0);
+ Assert.NotEmpty(data.GetAnalyzers());
+ });
}
[Fact]
@@ -87,7 +96,7 @@ public void GetAnalyzersNoHosting()
[Fact]
public void GetDiagnostics()
{
- using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath, BasicAnalyzerHost.DefaultKind);
+ using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath, BasicAnalyzerKind.None);
var data = reader.ReadCompilationData(0);
Assert.NotEmpty(data.GetDiagnostics());
}
@@ -95,7 +104,7 @@ public void GetDiagnostics()
[Fact]
public async Task GetAllDiagnostics()
{
- using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath, BasicAnalyzerHost.DefaultKind);
+ using var reader = CompilerLogReader.Create(Fixture.ClassLib.Value.CompilerLogPath, BasicAnalyzerKind.None);
var data = reader.ReadCompilationData(0);
Assert.NotEmpty(await data.GetAllDiagnosticsAsync());
}
@@ -103,32 +112,35 @@ public async Task GetAllDiagnostics()
[Fact]
public void GetCompilationAfterGeneratorsDiagnostics()
{
- using var reader = CompilerLogReader.Create(
- Fixture.Console.Value.CompilerLogPath,
- BasicAnalyzerHost.DefaultKind);
- var rawData = reader.ReadRawCompilationData(0).Item2;
- var analyzers = rawData.Analyzers
- .Where(x => x.FileName != "Microsoft.CodeAnalysis.NetAnalyzers.dll")
- .ToList();
- BasicAnalyzerHost host = DotnetUtil.IsNetCore
- ? new BasicAnalyzerHostInMemory(reader, analyzers)
- : new BasicAnalyzerHostOnDisk(reader, analyzers);
- var data = (CSharpCompilationData)reader.ReadCompilationData(0);
- data = new CSharpCompilationData(
- data.CompilerCall,
- data.Compilation,
- data.ParseOptions,
- data.EmitOptions,
- data.EmitData,
- data.AdditionalTexts,
- host,
- data.AnalyzerConfigOptionsProvider);
- _ = data.GetCompilationAfterGenerators(out var diagnostics);
- Assert.NotEmpty(diagnostics);
+ RunInContext(Fixture.Console.Value.CompilerLogPath, static (testOutputHelper, logFilePath) =>
+ {
+ using var reader = CompilerLogReader.Create(
+ logFilePath,
+ BasicAnalyzerHost.DefaultKind);
+ var rawData = reader.ReadRawCompilationData(0).Item2;
+ var analyzers = rawData.Analyzers
+ .Where(x => x.FileName != "Microsoft.CodeAnalysis.NetAnalyzers.dll")
+ .ToList();
+ BasicAnalyzerHost host = DotnetUtil.IsNetCore
+ ? new BasicAnalyzerHostInMemory(reader, analyzers)
+ : new BasicAnalyzerHostOnDisk(reader, analyzers);
+ var data = (CSharpCompilationData)reader.ReadCompilationData(0);
+ data = new CSharpCompilationData(
+ data.CompilerCall,
+ data.Compilation,
+ data.ParseOptions,
+ data.EmitOptions,
+ data.EmitData,
+ data.AdditionalTexts,
+ host,
+ data.AnalyzerConfigOptionsProvider);
+ _ = data.GetCompilationAfterGenerators(out var diagnostics);
+ Assert.NotEmpty(diagnostics);
+ });
}
[Theory]
- [MemberData(nameof(GetSupportedBasicAnalyzerKinds))]
+ [MemberData(nameof(GetSimpleBasicAnalyzerKinds))]
public void GetGeneratedSyntaxTrees(BasicAnalyzerKind basicAnalyzerKind)
{
using var reader = CompilerLogReader.Create(Fixture.Console.Value.CompilerLogPath, basicAnalyzerKind);
diff --git a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
index 929eab4..d8306d8 100644
--- a/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
@@ -179,19 +179,13 @@ public void AdditionalFiles()
Assert.NotNull(options);
}
- [Fact]
- public void AnalyzerLoadOptions()
+ [Theory]
+ [MemberData(nameof(GetSupportedBasicAnalyzerKinds))]
+ public void AnalyzerLoadOptions(BasicAnalyzerKind basicAnalyzerKind)
{
- var any = false;
- foreach (BasicAnalyzerKind kind in Enum.GetValues(typeof(BasicAnalyzerKind)))
+ RunInContext((FilePath: Fixture.Console.Value.CompilerLogPath, Kind: basicAnalyzerKind), static (testOutputHelper, state) =>
{
- if (!BasicAnalyzerHost.IsSupported(kind))
- {
- continue;
- }
- any = true;
-
- using var reader = CompilerLogReader.Create(Fixture.Console.Value.CompilerLogPath, kind);
+ using var reader = CompilerLogReader.Create(state.FilePath, state.Kind);
var data = reader.ReadCompilationData(0);
var compilation = data.GetCompilationAfterGenerators(out var diagnostics);
Assert.Empty(diagnostics);
@@ -206,9 +200,7 @@ public void AnalyzerLoadOptions()
}
Assert.True(found);
data.BasicAnalyzerHost.Dispose();
- }
-
- Assert.True(any);
+ });
}
[Theory]
diff --git a/src/Basic.CompilerLog.UnitTests/SolutionReaderTests.cs b/src/Basic.CompilerLog.UnitTests/SolutionReaderTests.cs
index b72c104..a182504 100644
--- a/src/Basic.CompilerLog.UnitTests/SolutionReaderTests.cs
+++ b/src/Basic.CompilerLog.UnitTests/SolutionReaderTests.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Xunit;
@@ -42,7 +43,7 @@ private Solution GetSolution(string compilerLogFilePath, BasicAnalyzerKind basic
}
[Theory]
- [MemberData(nameof(GetSupportedBasicAnalyzerKinds))]
+ [MemberData(nameof(GetSimpleBasicAnalyzerKinds))]
public async Task DocumentsGeneratedDefaultHost(BasicAnalyzerKind basicAnalyzerKind)
{
var solution = GetSolution(Fixture.Console.Value.CompilerLogPath, basicAnalyzerKind);
diff --git a/src/Basic.CompilerLog.UnitTests/TestBase.cs b/src/Basic.CompilerLog.UnitTests/TestBase.cs
index f5548fe..35e4083 100644
--- a/src/Basic.CompilerLog.UnitTests/TestBase.cs
+++ b/src/Basic.CompilerLog.UnitTests/TestBase.cs
@@ -1,13 +1,17 @@
using Basic.CompilerLog.Util;
+using Basic.CompilerLog.Util.Impl;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
+using Xunit.Sdk;
namespace Basic.CompilerLog.UnitTests;
@@ -16,11 +20,17 @@ public abstract class TestBase : IDisposable
private static readonly object Guard = new();
internal static readonly Encoding DefaultEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
+
+ private List BadAssemblyLoadList { get; } = new();
internal ITestOutputHelper TestOutputHelper { get; }
internal TempDir Root { get; }
internal Util.LogReaderState State { get; }
internal string RootDirectory => Root.DirectoryPath;
+ ///
+ /// Get all of the supported
+ ///
+ ///
public static IEnumerable