Skip to content

Commit

Permalink
Add APIs to read logs from a Stream, not just file path.
Browse files Browse the repository at this point in the history
  • Loading branch information
KirillOsenkov committed Aug 2, 2018
1 parent be3bdca commit b06d2ce
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 158 deletions.
73 changes: 73 additions & 0 deletions src/StructuredLogger.Tests/BinaryLoggerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using Microsoft.Build.Logging;
using Microsoft.Build.Logging.StructuredLogger;
using StructuredLogger.Tests;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.UnitTests
{
public class BinaryLoggerTests : IDisposable
{
private static string s_testProject = @"
<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
<PropertyGroup>
<TestProperty>Test</TestProperty>
</PropertyGroup>
<ItemGroup>
<TestItem Include=""Test"" />
</ItemGroup>
<Target Name='Target1'>
<Message Text='MessageOutputText'/>
</Target>
<Target Name='Target2' AfterTargets='Target1'>
<Exec Command='echo a'/>
</Target>
</Project>";

public BinaryLoggerTests(ITestOutputHelper output)
{
}

[Fact]
public void TestBinaryLoggerRoundtrip()
{
var binLog = "1.binlog";
var binaryLogger = new BinaryLogger();
binaryLogger.Parameters = binLog;
MSBuild.BuildProject(s_testProject, binaryLogger);

var build = Serialization.Read(binLog);
Assert.Equal("", GetProperty(build));
Serialization.Write(build, "1.xml");

Serialization.Write(build, "1.buildlog");
build = Serialization.Read("1.buildlog");
Assert.Equal("", GetProperty(build));
Serialization.Write(build, "2.xml");

Assert.False(Differ.AreDifferent("1.xml", "2.xml"));

build = XlinqLogReader.ReadFromXml("1.xml");
Assert.Equal("", GetProperty(build));
Serialization.Write(build, "3.xml");
Assert.False(Differ.AreDifferent("1.xml", "3.xml"));

build = Serialization.Read("1.xml");
Assert.Equal("", GetProperty(build));
Serialization.Write(build, "4.xml");

Assert.False(Differ.AreDifferent("1.xml", "4.xml"));
}

private static string GetProperty(Logging.StructuredLogger.Build build)
{
var property = build.FindFirstDescendant<Project>().FindChild<Folder>("Properties").FindChild<Property>(p => p.Name == "FrameworkSDKRoot").Value;
return property;
}

public void Dispose()
{
}
}
}
20 changes: 10 additions & 10 deletions src/StructuredLogger.Tests/BinarySerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ public void TestWriter()
Serialization.Write(build, @"D:\1.buildlog");
}

//[Fact]
[Fact]
public void SimpleBuild()
{
var build = new Build();
build.Succeeded = true;
build.AddChild(new Message() { Text = "MessageText" });
build.AddChild(new Property() { Name = "PropertyName", Value = "PropertyValue" });
var file1 = @"D:\1.xml";
var file2 = @"D:\2.xml";
Serialization.Write(build, file1);
var filePath = @"D:\1.buildlog";
Serialization.Write(build, filePath);
build = Serialization.Read(filePath);
Serialization.Write(build, file2);
Serialization.Write(build, @"D:\2.buildlog");
Differ.AreDifferent(file1, file2);
var xmlFile1 = @"1.xml";
var xmlFile2 = @"2.xml";
Serialization.Write(build, xmlFile1);
var buildLogFile = @"1.buildlog";
Serialization.Write(build, buildLogFile);
build = Serialization.Read(buildLogFile);
Serialization.Write(build, xmlFile2);
Serialization.Write(build, @"2.buildlog");
Differ.AreDifferent(xmlFile1, xmlFile2);
}
}
}
2 changes: 1 addition & 1 deletion src/StructuredLogger.Tests/Differ.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static bool AreDifferent(string file1, string file2)
var destination = File.ReadAllText(file2);
if (source != destination)
{
Process.Start("devenv", $"/diff \"{file1}\" \"{file2}\"");
// Process.Start("devenv", $"/diff \"{Path.GetFullPath(file1)}\" \"{Path.GetFullPath(file2)}\"");
return true;
}
else
Expand Down
58 changes: 58 additions & 0 deletions src/StructuredLogger.Tests/MSBuild.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.IO;
using System.Xml;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;

namespace StructuredLogger.Tests
{
public class MSBuild
{
public static bool BuildProject(string projectText, params ILogger[] loggers)
{
Project project = CreateInMemoryProject(projectText, loggers: loggers);
bool success = project.Build(loggers);
return success;
}

public static Project CreateInMemoryProject(string projectText, ProjectCollection projectCollection = null, params ILogger[] loggers)
{
XmlReaderSettings readerSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore };
projectCollection = projectCollection ?? new ProjectCollection();

Project project = new Project(
XmlReader.Create(new StringReader(CleanupFileContents(projectText)), readerSettings),
null,
toolsVersion: null,
projectCollection: projectCollection);

Guid guid = Guid.NewGuid();
project.FullPath = Path.GetFullPath("Temporary" + guid.ToString("N") + ".csproj");
project.ReevaluateIfNecessary();

return project;
}

const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";

/// <summary>
/// Does certain replacements in a string representing the project file contents.
/// This makes it easier to write unit tests because the author doesn't have
/// to worry about escaping double-quotes, etc.
/// </summary>
/// <param name="projectFileContents"></param>
/// <returns></returns>
internal static string CleanupFileContents(string projectFileContents)
{
// Replace reverse-single-quotes with double-quotes.
projectFileContents = projectFileContents.Replace("`", "\"");

// Place the correct MSBuild namespace into the <Project> tag.
projectFileContents = projectFileContents.Replace("msbuildnamespace", msbuildNamespace);
projectFileContents = projectFileContents.Replace("msbuilddefaulttoolsversion", "15.0");
projectFileContents = projectFileContents.Replace("msbuildassemblyversion", "15.1.0.0");

return projectFileContents;
}
}
}
3 changes: 1 addition & 2 deletions src/StructuredLogger.Tests/Roundtrip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ public void RoundtripTest()
public void ReadBinaryLogRecords()
{
var reader = new BinaryLogReplayEventSource();
var records = reader.ReadRecords(@"D:\msbuild.binlog").ToArray();
var count = records.Length;
var records = reader.ReadRecords(@"C:\temp\msbuild.binlog");
foreach (var record in records)
{
var t = record.Args;
Expand Down
2 changes: 1 addition & 1 deletion src/StructuredLogger.Tests/StructuredLogger.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<AssemblyName>StructuredLogger.Tests</AssemblyName>
<TargetFrameworks>net46</TargetFrameworks>
<TargetFramework>net46</TargetFramework>
<NBGV_DoNotEmitNonVersionCustomAttributes>true</NBGV_DoNotEmitNonVersionCustomAttributes>
</PropertyGroup>
<ItemGroup>
Expand Down
29 changes: 20 additions & 9 deletions src/StructuredLogger/BinaryLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,30 @@ public class BinaryLog
{
public static Build ReadBuild(string filePath)
{
var eventSource = new BinaryLogReplayEventSource();
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var projectImportsZipFile = Path.ChangeExtension(filePath, ".ProjectImports.zip");
byte[] projectImportsArchive = null;
if (File.Exists(projectImportsZipFile))
{
projectImportsArchive = File.ReadAllBytes(projectImportsZipFile);
}

byte[] sourceArchive = null;
return ReadBuild(stream, projectImportsArchive);
}
}

public static Build ReadBuild(Stream stream, byte[] projectImportsArchive = null)
{
var eventSource = new BinaryLogReplayEventSource();

Build build = null;

eventSource.OnBlobRead += (kind, bytes) =>
{
if (kind == BinaryLogRecordKind.ProjectImportArchive)
{
sourceArchive = bytes;
projectImportsArchive = bytes;
}
};
eventSource.OnException += ex =>
Expand All @@ -37,7 +50,7 @@ public static Build ReadBuild(string filePath)
build = structuredLogger.Construction.Build;

var sw = Stopwatch.StartNew();
eventSource.Replay(filePath);
eventSource.Replay(stream);
var elapsed = sw.Elapsed;

structuredLogger.Shutdown();
Expand All @@ -48,16 +61,14 @@ public static Build ReadBuild(string filePath)
if (build == null)
{
build = new Build() { Succeeded = false };
build.AddChild(new Error() { Text = "Error when opening the file: " + filePath });
build.AddChild(new Error() { Text = "Error when opening the log file." });
}

var projectImportsZip = Path.ChangeExtension(filePath, ".ProjectImports.zip");
if (sourceArchive == null && File.Exists(projectImportsZip))
if (build.SourceFilesArchive == null && projectImportsArchive != null)
{
sourceArchive = File.ReadAllBytes(projectImportsZip);
build.SourceFilesArchive = projectImportsArchive;
}

build.SourceFilesArchive = sourceArchive;
// build.AddChildAtBeginning(new Message { Text = "Elapsed: " + elapsed.ToString() });

return build;
Expand Down
Loading

0 comments on commit b06d2ce

Please sign in to comment.