Skip to content

Commit

Permalink
more
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredpar committed Nov 6, 2024
1 parent 6cd5ff4 commit c3120f9
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 46 deletions.
55 changes: 31 additions & 24 deletions src/Basic.CompilerLog.UnitTests/CompilerLogFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

namespace Basic.CompilerLog.UnitTests;

public readonly struct LogData(string compilerLogPath, string? binaryLogPath)
public readonly struct LogData(string compilerLogPath, string? binaryLogPath, bool supportsNoneHost = true)
{
public string CompilerLogPath { get; } = compilerLogPath;
public string? BinaryLogPath { get; } = binaryLogPath;
public bool SupportsNoneHost { get; } = supportsNoneHost;

public override string ToString() => $"{Path.GetFileName(CompilerLogPath)}";
}
Expand All @@ -40,14 +41,14 @@ public void Dispose()

public sealed class CompilerLogFixture : FixtureBase, IDisposable
{
private readonly ImmutableArray<Lazy<LogData>> _allLogs;
internal ImmutableArray<Lazy<LogData>> AllLogs { get; }

/// <summary>
/// Storage directory for all the generated artifacts and scatch directories
/// Storage directory for all the generated artifacts and scratch directories
/// </summary>
internal string StorageDirectory { get; }

internal string ScratchDirecectory { get; }
internal string ScratchDirectory { get; }

/// <summary>
/// Directory that holds the log files
Expand Down Expand Up @@ -105,9 +106,9 @@ public CompilerLogFixture(IMessageSink messageSink)
{
StorageDirectory = Path.Combine(Path.GetTempPath(), nameof(CompilerLogFixture), Guid.NewGuid().ToString("N"));
ComplogDirectory = Path.Combine(StorageDirectory, "logs");
ScratchDirecectory = Path.Combine(StorageDirectory, "scratch dir");
ScratchDirectory = Path.Combine(StorageDirectory, "scratch dir");
Directory.CreateDirectory(ComplogDirectory);
Directory.CreateDirectory(ScratchDirecectory);
Directory.CreateDirectory(ScratchDirectory);

var testArtifactsDir = Environment.GetEnvironmentVariable("TEST_ARTIFACTS_PATH");
if (testArtifactsDir is not null)
Expand Down Expand Up @@ -490,21 +491,21 @@ partial class Util {
""";
File.WriteAllText(Path.Combine(scratchPath, "Program.cs"), program, TestBase.DefaultEncoding);
RunDotnetCommand("build -bl -nr:false", scratchPath);
});
}, supportsNoneHost: false);
}

WithResource("linux-console.complog");
WithResource("windows-console.complog");

_allLogs = builder.ToImmutable();
Lazy<LogData> WithBuild(string name, Action<string> action, bool expectDiagnosticMessages = false)
AllLogs = builder.ToImmutable();
Lazy<LogData> WithBuild(string name, Action<string> action, bool expectDiagnosticMessages = false, bool supportsNoneHost = true)
{
var lazy = new Lazy<LogData>(() =>
{
var start = DateTime.UtcNow;
try
{
var scratchPath = Path.Combine(ScratchDirecectory, Guid.NewGuid().ToString("N"));
var scratchPath = Path.Combine(ScratchDirectory, Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(scratchPath);
messageSink.OnDiagnosticMessage($"Starting {name} in {scratchPath}");
RunDotnetCommand("new globaljson --sdk-version 8.0.400", scratchPath);
Expand All @@ -529,7 +530,7 @@ Lazy<LogData> WithBuild(string name, Action<string> action, bool expectDiagnosti
Assert.Empty(diagnostics);
}
return new LogData(complogFilePath, binlogFilePath);
return new LogData(complogFilePath, binlogFilePath, supportsNoneHost);
}
catch (Exception ex)
{
Expand All @@ -553,15 +554,16 @@ void WithResource(string name)
}
}

public async IAsyncEnumerable<LogData> GetAllLogDatas(ITestOutputHelper testOutputHelper)
public async IAsyncEnumerable<LogData> GetAllLogData(ITestOutputHelper testOutputHelper, BasicAnalyzerKind? kind = null)
{
var start = DateTime.UtcNow;
foreach (var logData in _allLogs)
foreach (var lazyLogData in AllLogs)
{
if (logData.IsValueCreated)
LogData logData;
if (lazyLogData.IsValueCreated)
{
testOutputHelper.WriteLine($"Using cached value");
yield return logData.Value;
logData = lazyLogData.Value;
}
else
{
Expand All @@ -571,7 +573,7 @@ await Task.Factory.StartNew(() =>
try
{
testOutputHelper.WriteLine($"Starting {nameof(GetAllCompilerLogs)}");
tcs.SetResult(logData.Value);
tcs.SetResult(lazyLogData.Value);
testOutputHelper.WriteLine($"Finished {nameof(GetAllCompilerLogs)} {(DateTime.UtcNow - start).TotalSeconds:F2}s");
}
catch (Exception ex)
Expand All @@ -580,7 +582,12 @@ await Task.Factory.StartNew(() =>
}
}, TaskCreationOptions.LongRunning);

yield return await tcs.Task;
logData = await tcs.Task;
}

if (kind is not BasicAnalyzerKind.None || logData.SupportsNoneHost)
{
yield return logData;
}
}
}
Expand All @@ -593,7 +600,7 @@ await Task.Factory.StartNew(() =>
public FileLockHold LockScratchDirectory()
{
var list = new List<Stream>();
foreach (var filePath in Directory.EnumerateFiles(ScratchDirecectory, "*", SearchOption.AllDirectories))
foreach (var filePath in Directory.EnumerateFiles(ScratchDirectory, "*", SearchOption.AllDirectories))
{
// Don't lock the binlog or complogs as that is what the code is actually going to be reading
if (Path.GetExtension(filePath) is ".binlog" or ".complog")
Expand All @@ -607,9 +614,9 @@ public FileLockHold LockScratchDirectory()
return new FileLockHold(list);
}

public async IAsyncEnumerable<string> GetAllLogs(ITestOutputHelper testOutputHelper)
public async IAsyncEnumerable<string> GetAllLogs(ITestOutputHelper testOutputHelper, BasicAnalyzerKind? kind = null)
{
await foreach (var logData in GetAllLogDatas(testOutputHelper))
await foreach (var logData in GetAllLogData(testOutputHelper, kind))
{
yield return logData.CompilerLogPath;
if (logData.BinaryLogPath is { } binaryLogPath)
Expand All @@ -619,17 +626,17 @@ public async IAsyncEnumerable<string> GetAllLogs(ITestOutputHelper testOutputHel
}
}

public async IAsyncEnumerable<string> GetAllCompilerLogs(ITestOutputHelper testOutputHelper)
public async IAsyncEnumerable<string> GetAllCompilerLogs(ITestOutputHelper testOutputHelper, BasicAnalyzerKind? kind = null)
{
await foreach (var logData in GetAllLogDatas(testOutputHelper))
await foreach (var logData in GetAllLogData(testOutputHelper, kind))
{
yield return logData.CompilerLogPath;
}
}

public async IAsyncEnumerable<string> GetAllBinaryLogs(ITestOutputHelper testOutputHelper)
public async IAsyncEnumerable<string> GetAllBinaryLogs(ITestOutputHelper testOutputHelper, BasicAnalyzerKind? kind = null)
{
await foreach (var logData in GetAllLogDatas(testOutputHelper))
await foreach (var logData in GetAllLogData(testOutputHelper, kind))
{
if (logData.BinaryLogPath is { } binaryLog)
{
Expand Down
14 changes: 14 additions & 0 deletions src/Basic.CompilerLog.UnitTests/CompilerLogReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,20 @@ public void NoneHostAddsNoGeneratorIfNoGeneratedSource()
Assert.Single(data.AnalyzerReferences);
}

[WindowsFact]
public void HasAllGeneratedFileContent()
{
Run(Fixture.Console.Value.CompilerLogPath, true);
Run(Fixture.ConsoleWithNativePdb!.Value.CompilerLogPath, false);

void Run(string complogFilePath, bool expected)
{
using var reader = CompilerLogReader.Create(complogFilePath, BasicAnalyzerKind.None);
var compilerCall = reader.ReadCompilerCall(0);
Assert.Equal(expected, reader.HasAllGeneratedFileContent(compilerCall));
}
}

[Fact]
public void NoneHostNativePdb()
{
Expand Down
53 changes: 38 additions & 15 deletions src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ public UsingAllCompilerLogTests(ITestOutputHelper testOutputHelper, CompilerLogF
Fixture = fixture;
}

[Fact]
public async Task GetAllLogData()
{
var count = 0;
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper, BasicAnalyzerKind.OnDisk))
{
count++;
}
Assert.Equal(Fixture.AllLogs.Length, count);

count = 0;
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper, BasicAnalyzerKind.None))
{
count++;
}
Assert.Equal(Fixture.AllLogs.Length - 1, count);

Check failure on line 39 in src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs

View workflow job for this annotation

GitHub Actions / .NET Test Results

Basic.CompilerLog.UnitTests.UsingAllCompilerLogTests ► GetAllLogData

Failed test found in: TestResults-Test-Linux.trx Error: Assert.Equal() Failure: Values differ Expected: 10 Actual: 11
Raw output
Assert.Equal() Failure: Values differ
Expected: 10
Actual:   11
   at Basic.CompilerLog.UnitTests.UsingAllCompilerLogTests.GetAllLogData() in /home/runner/work/complog/complog/src/Basic.CompilerLog.UnitTests/UsingAllCompilerLogTests.cs:line 39
--- End of stack trace from previous location ---
}

[Fact]
public async Task EmitToDisk()
{
Expand All @@ -32,6 +50,11 @@ public async Task EmitToDisk()
using var reader = CompilerLogReader.Create(complogPath, basicAnalyzerKind: BasicAnalyzerKind.None);
foreach (var data in reader.ReadAllCompilationData())
{
if (!reader.HasAllGeneratedFileContent(data.CompilerCall))
{
continue;
}
using var testDir = new TempDir();
TestOutputHelper.WriteLine($"{Path.GetFileName(complogPath)}: {data.CompilerCall.ProjectFileName} ({data.CompilerCall.TargetFramework})");
var emitResult = data.EmitToDisk(testDir.DirectoryPath);
Expand Down Expand Up @@ -73,13 +96,11 @@ public async Task EmitToDisk()
public async Task GeneratedFilePathsNoneHost()
{
char[] illegalChars = ['<', '>'];
var count = 0;
await foreach (var logPath in Fixture.GetAllLogs(TestOutputHelper))
{
count++;
TestOutputHelper.WriteLine(logPath);
using var reader = CompilerCallReaderUtil.Create(logPath, BasicAnalyzerKind.None);
foreach (var data in reader.ReadAllCompilationData())
foreach (var data in reader.ReadAllCompilationData(reader.HasAllGeneratedFileContent))
{
TestOutputHelper.WriteLine($"\t{data.CompilerCall.ProjectFileName} ({data.CompilerCall.TargetFramework})");
var generatedTrees = data.GetGeneratedSyntaxTrees();
Expand All @@ -99,20 +120,17 @@ public async Task GeneratedFilePathsNoneHost()
public async Task EmitToMemory(BasicAnalyzerKind basicAnalyzerKind)
{
TestOutputHelper.WriteLine($"BasicAnalyzerKind: {basicAnalyzerKind}");
var count = 0;
await foreach (var logPath in Fixture.GetAllLogs(TestOutputHelper))
{
count++;
TestOutputHelper.WriteLine(logPath);
using var reader = CompilerCallReaderUtil.Create(logPath, basicAnalyzerKind);
foreach (var data in reader.ReadAllCompilationData())
foreach (var data in reader.ReadAllCompilationData(cc => basicAnalyzerKind != BasicAnalyzerKind.None || reader.HasAllGeneratedFileContent(cc)))
{
TestOutputHelper.WriteLine($"\t{data.CompilerCall.ProjectFileName} ({data.CompilerCall.TargetFramework})");
var emitResult = data.EmitToMemory();
AssertEx.Success(TestOutputHelper, emitResult);
}
}
Assert.True(count >= 10);
}

/// <summary>
Expand All @@ -122,7 +140,7 @@ public async Task EmitToMemory(BasicAnalyzerKind basicAnalyzerKind)
[Fact]
public async Task EmitToMemoryCompilerLogWithSeparateState()
{
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper))
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper, BasicAnalyzerKind.None))
{
TestOutputHelper.WriteLine(complogPath);
using var state = new Util.LogReaderState(baseDir: Root.NewDirectory());
Expand Down Expand Up @@ -172,7 +190,7 @@ public async Task CommandLineArguments()
[Fact]
public async Task ClassifyAll()
{
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper))
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper, BasicAnalyzerKind.None))
{
using var reader = SolutionReader.Create(complogPath, BasicAnalyzerKind.None);
using var workspace = new AdhocWorkspace();
Expand All @@ -196,9 +214,14 @@ public async Task ExportAndBuild(bool includeAnalyzers)
{
using var fileLock = Fixture.LockScratchDirectory();
var list = new List<Task>();
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper))
await foreach (var logData in Fixture.GetAllLogData(TestOutputHelper))
{
var task = Task.Run(() => ExportUtilTests.TestExport(TestOutputHelper, complogPath, expectedCount: null, includeAnalyzers, runBuild: true));
if (!includeAnalyzers && !logData.SupportsNoneHost)
{
continue;
}

var task = Task.Run(() =>ExportUtilTests.TestExport(TestOutputHelper, logData.CompilerLogPath, expectedCount: null, includeAnalyzers, runBuild: true));
list.Add(task);
}

Expand All @@ -210,10 +233,10 @@ public async Task ExportAndBuild(bool includeAnalyzers)
[InlineData(false)]
public async Task LoadAllCore(bool none)
{
var options = none ? BasicAnalyzerKind.None : BasicAnalyzerHost.DefaultKind;
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper))
var kind = none ? BasicAnalyzerKind.None : BasicAnalyzerHost.DefaultKind;
await foreach (var complogPath in Fixture.GetAllCompilerLogs(TestOutputHelper, kind))
{
using var reader = SolutionReader.Create(complogPath, options);
using var reader = SolutionReader.Create(complogPath, kind);
var workspace = new AdhocWorkspace();
var solution = workspace.AddSolution(reader.ReadSolutionInfo());
Assert.NotEmpty(solution.Projects);
Expand All @@ -228,7 +251,7 @@ public async Task LoadAllCore(bool none)
[Fact]
public async Task VerifyConsistentOptions()
{
await foreach (var logData in Fixture.GetAllLogDatas(TestOutputHelper))
await foreach (var logData in Fixture.GetAllLogData(TestOutputHelper))
{
if (logData.BinaryLogPath is null)
{
Expand Down
4 changes: 4 additions & 0 deletions src/Basic.CompilerLog.Util/BinaryLogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,10 @@ public List<CompilerAssemblyData> ReadAllCompilerAssemblies()
.ToList();
}

/// <inheritdoc cref="ICompilerCallReader.HasAllGeneratedFileContent(CompilerCall)"/>
public bool HasAllGeneratedFileContent(CompilerCall compilerCall) =>
RoslynUtil.HasGeneratedFilesInPdb(ReadCommandLineArguments(compilerCall));

/// <summary>
/// Attempt to add all the generated files from generators. When successful the generators
/// don't need to be run when re-hydrating the compilation.
Expand Down
9 changes: 2 additions & 7 deletions src/Basic.CompilerLog.Util/CompilerLogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -620,13 +620,8 @@ public SourceText ReadSourceText(SourceTextData sourceTextData)
return GetSourceText(contentHash, sourceTextData.ChecksumAlgorithm, canBeEmbedded: false);
}

/// <summary>
/// Are all the generated files contained in the data?
/// </summary>
/// <remarks>
/// Older versions of compiler log aren't guaranteed to have HasGeneratedFilesInPdb set
/// </remarks>
internal bool HasAllGeneratedFileContent(CompilerCall compilerCall) =>
/// <inheritdoc cref="ICompilerCallReader.HasAllGeneratedFileContent(CompilerCall)"/>
public bool HasAllGeneratedFileContent(CompilerCall compilerCall) =>
HasAllGeneratedFileContent(GetOrReadCompilationDataPack(compilerCall));

private bool HasAllGeneratedFileContent(CompilationDataPack dataPack) =>
Expand Down
10 changes: 10 additions & 0 deletions src/Basic.CompilerLog.Util/ICompilerCallReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,14 @@ public interface ICompilerCallReader : IDisposable
public void CopyAssemblyBytes(AssemblyData referenceData, Stream stream);

public MetadataReference ReadMetadataReference(ReferenceData referenceData);

/// <summary>
/// Are all the generated files contained in the data?
/// </summary>
/// <remarks>
/// This can fail in a few cases
/// - Older compiler log versions don't encode all the data
/// - Compilations using native PDBS don't have this capability
/// </remarks>
public bool HasAllGeneratedFileContent(CompilerCall compilerCall);
}

0 comments on commit c3120f9

Please sign in to comment.