Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Blazor SWA Baseline Mismatched Assets Logging #27542

Merged
merged 11 commits into from
Nov 3, 2022
152 changes: 148 additions & 4 deletions src/Tests/Microsoft.NET.Sdk.Razor.Tests/AspNetSdkBaselineTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ namespace Microsoft.NET.Sdk.Razor.Tests
public class AspNetSdkBaselineTest : AspNetSdkTest
{
private static readonly JsonSerializerOptions BaselineSerializationOptions = new() { WriteIndented = true };
private static readonly string BaselineGenerationInstructions =
@"If the difference in baselines is expected, please re-generate the baselines.
Note, baseline generation must be done on a Windows device.
Start by ensuring you're dogfooding the SDK from the current branch (dotnet --version should be '*.0.0-dev').
If you're not on the dogfood sdk, from the root of the repository run:
1. dotnet clean
2. .\restore.cmd
3. .\build.cmd
4. .\eng\dogfood.cmd

Then, using the dogfood SDK run the .\src\RazorSdk\update-test-baselines.ps1 script.";

protected static readonly string DotNetJSHashRegexPattern = "\\.[a-z0-9]{10}\\.js";
protected static readonly string DotNetJSHashTemplate = ".[[hash]].js";

Expand Down Expand Up @@ -352,8 +364,8 @@ internal void AssertManifest(
manifest.BasePath.Should().Be(expected.BasePath);
manifest.Mode.Should().Be(expected.Mode);
manifest.ManifestType.Should().Be(expected.ManifestType);
manifest.ReferencedProjectsConfiguration.Count().Should().Be(expected.ReferencedProjectsConfiguration.Count());

manifest.ReferencedProjectsConfiguration.Should().HaveSameCount(expected.ReferencedProjectsConfiguration);

// Relax the check for project reference configuration items see
// https://github.com/dotnet/sdk/pull/27381#issuecomment-1228764471
Expand All @@ -363,8 +375,139 @@ internal void AssertManifest(
// .BeEquivalentTo(expected.ReferencedProjectsConfiguration.OrderBy(cm => cm.Identity));

manifest.DiscoveryPatterns.OrderBy(dp => dp.Name).Should().BeEquivalentTo(expected.DiscoveryPatterns.OrderBy(dp => dp.Name));
manifest.Assets.OrderBy(a => a.BasePath).ThenBy(a => a.RelativePath).ThenBy(a => a.AssetKind)
.Should().BeEquivalentTo(expected.Assets.OrderBy(a => a.BasePath).ThenBy(a => a.RelativePath).ThenBy(a => a.AssetKind));

var manifestAssets = manifest.Assets.OrderBy(a => a.BasePath).ThenBy(a => a.RelativePath).ThenBy(a => a.AssetKind);
var expectedAssets = expected.Assets.OrderBy(a => a.BasePath).ThenBy(a => a.RelativePath).ThenBy(a => a.AssetKind);

// If there's a mismatch in the number of assets, just print the strict difference in the asset `Identity`
if (manifestAssets.Count() != expectedAssets.Count())
{
ThrowAssetCountMismatchError(manifestAssets, expectedAssets);
}

// Otherwise, do a property level comparison of all assets
var manifestAssetsEnumerator = manifestAssets.GetEnumerator();
var expectedAssetsEnumerator = expectedAssets.GetEnumerator();

var differences = new List<string>();

do
{
var manifestAsset = manifestAssetsEnumerator.Current;
var expectedAsset = expectedAssetsEnumerator.Current;

if (manifestAsset is null && expectedAsset is null)
{
continue;
}

var assetDifferences = new List<string>();

if (manifestAsset.Identity != expectedAsset.Identity)
{
assetDifferences.Add($"Expected manifest Identity of {expectedAsset.Identity} but found {manifestAsset.Identity}.");
}
if (manifestAsset.SourceType != expectedAsset.SourceType)
{
assetDifferences.Add($"Expected manifest SourceType of {expectedAsset.SourceType} but found {manifestAsset.SourceType}.");
}
if (manifestAsset.SourceId != expectedAsset.SourceId)
{
assetDifferences.Add($"Expected manifest SourceId of {expectedAsset.SourceId} but found {manifestAsset.SourceId}.");
}
if (manifestAsset.ContentRoot != expectedAsset.ContentRoot)
{
assetDifferences.Add($"Expected manifest ContentRoot of {expectedAsset.ContentRoot} but found {manifestAsset.ContentRoot}.");
}
if (manifestAsset.BasePath != expectedAsset.BasePath)
{
assetDifferences.Add($"Expected manifest BasePath of {expectedAsset.BasePath} but found {manifestAsset.BasePath}.");
}
if (manifestAsset.RelativePath != expectedAsset.RelativePath)
{
assetDifferences.Add($"Expected manifest RelativePath of {expectedAsset.RelativePath} but found {manifestAsset.RelativePath}.");
}
if (manifestAsset.AssetKind != expectedAsset.AssetKind)
{
assetDifferences.Add($"Expected manifest AssetKind of {expectedAsset.AssetKind} but found {manifestAsset.AssetKind}.");
}
if (manifestAsset.AssetMode != expectedAsset.AssetMode)
{
assetDifferences.Add($"Expected manifest AssetMode of {expectedAsset.AssetMode} but found {manifestAsset.AssetMode}.");
}
if (manifestAsset.AssetRole != expectedAsset.AssetRole)
{
assetDifferences.Add($"Expected manifest AssetRole of {expectedAsset.AssetRole} but found {manifestAsset.AssetRole}.");
}
if (manifestAsset.RelatedAsset != expectedAsset.RelatedAsset)
{
assetDifferences.Add($"Expected manifest RelatedAsset of {expectedAsset.RelatedAsset} but found {manifestAsset.RelatedAsset}.");
}
if (manifestAsset.AssetTraitName != expectedAsset.AssetTraitName)
{
assetDifferences.Add($"Expected manifest AssetTraitName of {expectedAsset.AssetTraitName} but found {manifestAsset.AssetTraitName}.");
}
if (manifestAsset.AssetTraitValue != expectedAsset.AssetTraitValue)
{
assetDifferences.Add($"Expected manifest AssetTraitValue of {expectedAsset.AssetTraitValue} but found {manifestAsset.AssetTraitValue}.");
}
if (manifestAsset.CopyToOutputDirectory != expectedAsset.CopyToOutputDirectory)
{
assetDifferences.Add($"Expected manifest CopyToOutputDirectory of {expectedAsset.CopyToOutputDirectory} but found {manifestAsset.CopyToOutputDirectory}.");
}
if (manifestAsset.CopyToPublishDirectory != expectedAsset.CopyToPublishDirectory)
{
assetDifferences.Add($"Expected manifest CopyToPublishDirectory of {expectedAsset.CopyToPublishDirectory} but found {manifestAsset.CopyToPublishDirectory}.");
}
if (manifestAsset.OriginalItemSpec != expectedAsset.OriginalItemSpec)
{
assetDifferences.Add($"Expected manifest OriginalItemSpec of {expectedAsset.OriginalItemSpec} but found {manifestAsset.OriginalItemSpec}.");
}

if (assetDifferences.Any())
{
differences.Add(@$"
==================================================

For {expectedAsset.Identity}:

{string.Join(Environment.NewLine, assetDifferences)}

==================================================");
}

} while (manifestAssetsEnumerator.MoveNext() && expectedAssetsEnumerator.MoveNext());

differences.Should().BeEmpty(
@$" the generated manifest should match the expected baseline.

{BaselineGenerationInstructions}

");

static void ThrowAssetCountMismatchError(IEnumerable<StaticWebAsset> manifestAssets, IEnumerable<StaticWebAsset> expectedAssets)
{
var missingAssets = expectedAssets.Except(manifestAssets);
var unexpectedAssets = manifestAssets.Except(expectedAssets);

var differences = new List<string>();

if (missingAssets.Any())
{
differences.Add($@"The following expected assets weren't found in the manifest:
{string.Join($"{Environment.NewLine}\t", missingAssets.Select(a => a.Identity))}");
}

if (unexpectedAssets.Any())
{
differences.Add($@"The following additional unexpected assets were found in the manifest:
{string.Join($"{Environment.NewLine}\t", unexpectedAssets.Select(a => a.Identity))}");
}

throw new Exception($@"{string.Join(Environment.NewLine, differences)}

{BaselineGenerationInstructions}");
}
}
else
{
Expand Down Expand Up @@ -535,3 +678,4 @@ string TemplatizeRestorePath(string restorePath, string property)
}
}
}