Skip to content

Commit

Permalink
Add Blazor SWA Baseline Mismatched Assets Logging (#27542)
Browse files Browse the repository at this point in the history
* Add Blazor AssetDifferencesDetails

* Update AspNetSdkBaselineTest.cs

For https://github.com/dotnet/sdk/issues/27346

* Spacing

* Create blazor-swa-baseline-generation.md

* PR Feedback

* Remove instructions add script reference

* Property level comparison

* Added instructions

* Update AspNetSdkBaselineTest.cs

* Update AspNetSdkBaselineTest.cs
  • Loading branch information
TanayParikh authored Nov 3, 2022
1 parent 2c20d96 commit bacc17c
Showing 1 changed file with 148 additions and 4 deletions.
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)
}
}
}

0 comments on commit bacc17c

Please sign in to comment.