diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
index 38a666c61e7341..e429dd83d55bff 100644
--- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt
+++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
@@ -46,4 +46,5 @@ Wasm.Build.Tests.WasmTemplateTests
Wasm.Build.Tests.WorkloadTests
Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests
Wasm.Build.Tests.DebugLevelTests
+Wasm.Build.Tests.FingerprintingTests
Wasm.Build.Tests.PreloadingTests
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
index e9335ea19424f8..63f2fd2a3bd145 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
@@ -58,19 +58,6 @@ public void DefaultTemplate_AOT_WithWorkload(Configuration config, bool testUnic
PublishProject(info, config, new PublishOptions(AOT: true, UseCache: false));
}
- [Theory]
- [InlineData(Configuration.Debug, false)]
- [InlineData(Configuration.Release, false)]
- public void DefaultTemplate_CheckFingerprinting(Configuration config, bool expectFingerprintOnDotnetJs)
- {
- var extraProperty = expectFingerprintOnDotnetJs ?
- "truetrue" :
- "true";
- ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.BlazorBasicTestApp, "blz_checkfingerprinting", extraProperties: extraProperty);
- BlazorBuild(info, config, isNativeBuild: true);
- BlazorPublish(info, config, new PublishOptions(UseCache: false), isNativeBuild: true);
- }
-
// Disabling for now - publish folder can have more than one dotnet*hash*js, and not sure
// how to pick which one to check, for the test
//[Theory]
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
index 9915506700a784..01c9904b0a78c0 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
@@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
+using System.Threading.Tasks;
using Microsoft.NET.Sdk.WebAssembly;
using Xunit;
using Xunit.Abstractions;
@@ -96,4 +98,23 @@ public void BugRegression_60479_WithRazorClassLib()
Assert.Contains(bootJson.resources.lazyAssembly.Keys, f => f.StartsWith(razorClassLibraryName));
}
+
+
+ [Fact]
+ public async Task TestOverrideHtmlAssetPlaceholders()
+ {
+ var config = Configuration.Release;
+ string extraProperties = "true";
+ ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.BlazorBasicTestApp, "blz_import_map_html", extraProperties: extraProperties);
+ UpdateFile(Path.Combine("wwwroot", "index.html"), new Dictionary {
+ { """""", """ """ }
+ });
+
+ BuildProject(info, config);
+ BrowserRunOptions runOptions = new(config, TestScenario: "DotnetRun");
+ await RunForBuildWithDotnetRun(runOptions);
+
+ PublishProject(info, config, new PublishOptions(UseCache: false));
+ await RunForPublishWithWebServer(runOptions);
+ }
}
diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/AssertBundleOptions.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/AssertBundleOptions.cs
index c2fd74e11bf6d5..c258c21ddd7559 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/AssertBundleOptions.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/AssertBundleOptions.cs
@@ -14,5 +14,6 @@ public record AssertBundleOptions(
string BinFrameworkDir,
bool ExpectSymbolsFile = true,
bool AssertIcuAssets = true,
- bool AssertSymbolsFile = true
+ bool AssertSymbolsFile = true,
+ bool? ExpectDotnetJsFingerprinting = false
);
diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs b/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs
index 1e4df1407b692e..d928fc1e1b4069 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs
@@ -23,7 +23,6 @@ internal static class EnvironmentVariables
internal static readonly bool ShowBuildOutput = IsRunningOnCI || Environment.GetEnvironmentVariable("SHOW_BUILD_OUTPUT") is not null;
internal static readonly bool UseWebcil = Environment.GetEnvironmentVariable("USE_WEBCIL_FOR_TESTS") is "true";
internal static readonly bool UseFingerprinting = Environment.GetEnvironmentVariable("USE_FINGERPRINTING_FOR_TESTS") is "true";
- internal static readonly bool UseFingerprintingDotnetJS = Environment.GetEnvironmentVariable("WASM_FINGERPRINT_DOTNET_JS") is "true";
internal static readonly string? SdkDirName = Environment.GetEnvironmentVariable("SDK_DIR_NAME");
internal static readonly string? WasiSdkPath = Environment.GetEnvironmentVariable("WASI_SDK_PATH");
internal static readonly bool WorkloadsTestPreviousVersions = Environment.GetEnvironmentVariable("WORKLOADS_TEST_PREVIOUS_VERSIONS") is "true";
diff --git a/src/mono/wasm/Wasm.Build.Tests/FingerprintingTests.cs b/src/mono/wasm/Wasm.Build.Tests/FingerprintingTests.cs
new file mode 100644
index 00000000000000..556e80dd8c290f
--- /dev/null
+++ b/src/mono/wasm/Wasm.Build.Tests/FingerprintingTests.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit.Abstractions;
+using Xunit;
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+
+public class FingerprintingTests : WasmTemplateTestsBase
+{
+ public FingerprintingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
+ : base(output, buildContext)
+ {
+ }
+
+ [Fact]
+ public async Task TestOverrideHtmlAssetPlaceholdersWithFingerprinting()
+ {
+ var config = Configuration.Release;
+ string extraProperties = "true";
+ ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.WasmBasicTestApp, "OverrideHtmlAssetPlaceholders", extraProperties: extraProperties);
+ UpdateFile(Path.Combine("wwwroot", "index.html"), new Dictionary {
+ { """""", """ """ }
+ });
+ BuildProject(info, config, wasmFingerprintDotnetJs: true);
+ BrowserRunOptions runOptions = new(config, TestScenario: "DotnetRun");
+ await RunForBuildWithDotnetRun(runOptions);
+
+ PublishProject(info, config, new PublishOptions(UseCache: false), wasmFingerprintDotnetJs: true);
+ await RunForPublishWithWebServer(runOptions);
+ }
+}
diff --git a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
index 99a3489b5e6c18..30dbee46735d21 100644
--- a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@@ -41,8 +41,6 @@ public abstract class ProjectProviderBase(ITestOutputHelper _testOutput, string?
public bool IsFingerprintingEnabled => EnvironmentVariables.UseFingerprinting;
- public bool IsFingerprintingOnDotnetJsEnabled => EnvironmentVariables.UseFingerprintingDotnetJS;
-
// Returns the actual files on disk
public IReadOnlyDictionary AssertBasicBundle(AssertBundleOptions assertOptions)
{
@@ -82,7 +80,6 @@ public IReadOnlyDictionary FindAndAssertDotnetFiles(Asse
{
EnsureProjectDirIsSet();
return FindAndAssertDotnetFiles(binFrameworkDir: assertOptions.BinFrameworkDir,
- expectFingerprintOnDotnetJs: IsFingerprintingOnDotnetJsEnabled,
assertOptions,
superSet: GetAllKnownDotnetFilesToFingerprintMap(assertOptions),
expected: GetDotNetFilesExpectedSet(assertOptions)
@@ -94,11 +91,11 @@ public IReadOnlyDictionary FindAndAssertDotnetFiles(Asse
public IReadOnlyDictionary FindAndAssertDotnetFiles(
string binFrameworkDir,
- bool expectFingerprintOnDotnetJs,
AssertBundleOptions assertOptions,
IReadOnlyDictionary superSet,
IReadOnlySet expected)
{
+ var expectFingerprintOnDotnetJs = assertOptions.ExpectDotnetJsFingerprinting;
EnsureProjectDirIsSet();
var actual = new SortedDictionary();
@@ -109,6 +106,9 @@ public IReadOnlyDictionary FindAndAssertDotnetFiles(
SearchOption.TopDirectoryOnly)
.Order()
.ToList();
+
+ var comparisonLogging = new List();
+
foreach ((string expectedFilename, bool expectFingerprint) in superSet.OrderByDescending(kvp => kvp.Key))
{
string prefix = Path.GetFileNameWithoutExtension(expectedFilename);
@@ -121,7 +121,7 @@ public IReadOnlyDictionary FindAndAssertDotnetFiles(
return false;
string actualFilename = Path.GetFileName(actualFile);
- // _testOutput.WriteLine($"Comparing {expectedFilename} with {actualFile}, expectFingerprintOnDotnetJs: {expectFingerprintOnDotnetJs}, expectFingerprint: {expectFingerprint}");
+ comparisonLogging.Add($"Comparing {expectedFilename} with {actualFile}, expectFingerprint: {expectFingerprint}");
if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
expectFingerprintForThisFile: expectFingerprint))
@@ -149,12 +149,18 @@ public IReadOnlyDictionary FindAndAssertDotnetFiles(
}).ToList();
}
- // _testOutput.WriteLine($"Accepted count: {actual.Count}");
- // foreach (var kvp in actual)
- // _testOutput.WriteLine($"Accepted: \t[{kvp.Key}] = {kvp.Value}");
-
if (dotnetFiles.Any())
{
+ foreach (var message in comparisonLogging)
+ {
+ _testOutput.WriteLine(message);
+ }
+ _testOutput.WriteLine($"Accepted count: {actual.Count}");
+ foreach (var kvp in actual)
+ {
+ _testOutput.WriteLine($"Accepted: \t[{kvp.Key}] = {kvp.Value}");
+ }
+
throw new XunitException($"Found unknown files in {binFrameworkDir}:{Environment.NewLine} " +
$"{string.Join($"{Environment.NewLine} ", dotnetFiles.Select(f => Path.GetRelativePath(binFrameworkDir, f)))}{Environment.NewLine}" +
$"Add these to {nameof(GetAllKnownDotnetFilesToFingerprintMap)} method{Environment.NewLine}" +
@@ -173,7 +179,7 @@ private void AssertDotNetFilesSet(
IReadOnlySet expected,
IReadOnlyDictionary superSet,
IReadOnlyDictionary actualReadOnly,
- bool expectFingerprintOnDotnetJs,
+ bool? expectFingerprintOnDotnetJs,
string bundleDir)
{
EnsureProjectDirIsSet();
@@ -399,8 +405,8 @@ private string[] GetFilesMatchingNameConsideringFingerprinting(string filePath,
return dict;
}
- public bool ShouldCheckFingerprint(string expectedFilename, bool expectFingerprintOnDotnetJs, bool expectFingerprintForThisFile)
- => IsFingerprintingEnabled && ((expectedFilename == "dotnet.js" && expectFingerprintOnDotnetJs) || expectFingerprintForThisFile);
+ public bool ShouldCheckFingerprint(string expectedFilename, bool? expectFingerprintOnDotnetJs, bool expectFingerprintForThisFile)
+ => IsFingerprintingEnabled && ((expectedFilename == "dotnet.js" && expectFingerprintOnDotnetJs == true) || expectFingerprintForThisFile);
public static void AssertRuntimePackPath(string buildOutput, string targetFramework, RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded)
@@ -577,7 +583,7 @@ public BootJsonData AssertBootJson(AssertBundleOptions options)
string extension = Path.GetExtension(expectedFilename).Substring(1);
if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
- expectFingerprintOnDotnetJs: IsFingerprintingOnDotnetJsEnabled,
+ expectFingerprintOnDotnetJs: options.ExpectDotnetJsFingerprinting,
expectFingerprintForThisFile: expectFingerprint))
{
return Regex.Match(item, $"{prefix}{s_dotnetVersionHashRegex}{extension}").Success;
diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs
index 58dee636522e2c..1196d351cf3832 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTestsBase.cs
@@ -119,39 +119,45 @@ private void UpdateProjectFile(string projectFilePath, bool runAnalyzers, string
public virtual (string projectDir, string buildOutput) PublishProject(
ProjectInfo info,
Configuration configuration,
- bool? isNativeBuild = null) => // null for WasmBuildNative unset
- BuildProjectCore(info, configuration, _defaultPublishOptions, isNativeBuild);
+ bool? isNativeBuild = null,
+ bool? wasmFingerprintDotnetJs = null) => // null for unset properties
+ BuildProjectCore(info, configuration, _defaultPublishOptions, isNativeBuild, wasmFingerprintDotnetJs);
public virtual (string projectDir, string buildOutput) PublishProject(
ProjectInfo info,
Configuration configuration,
PublishOptions publishOptions,
- bool? isNativeBuild = null) =>
+ bool? isNativeBuild = null,
+ bool? wasmFingerprintDotnetJs = null) =>
BuildProjectCore(
info,
configuration,
publishOptions with { ExtraMSBuildArgs = $"{_extraBuildArgsPublish} {publishOptions.ExtraMSBuildArgs}" },
- isNativeBuild
+ isNativeBuild,
+ wasmFingerprintDotnetJs
);
public virtual (string projectDir, string buildOutput) BuildProject(
ProjectInfo info,
Configuration configuration,
- bool? isNativeBuild = null) => // null for WasmBuildNative unset
- BuildProjectCore(info, configuration, _defaultBuildOptions, isNativeBuild);
+ bool? isNativeBuild = null,
+ bool? wasmFingerprintDotnetJs = null) => // null for unset properties
+ BuildProjectCore(info, configuration, _defaultBuildOptions, isNativeBuild, wasmFingerprintDotnetJs);
public virtual (string projectDir, string buildOutput) BuildProject(
ProjectInfo info,
Configuration configuration,
BuildOptions buildOptions,
- bool? isNativeBuild = null) =>
- BuildProjectCore(info, configuration, buildOptions, isNativeBuild);
+ bool? isNativeBuild = null,
+ bool? wasmFingerprintDotnetJs = null) =>
+ BuildProjectCore(info, configuration, buildOptions, isNativeBuild, wasmFingerprintDotnetJs);
private (string projectDir, string buildOutput) BuildProjectCore(
ProjectInfo info,
Configuration configuration,
MSBuildOptions buildOptions,
- bool? isNativeBuild = null)
+ bool? isNativeBuild = null,
+ bool? wasmFingerprintDotnetJs = null)
{
if (buildOptions.AOT)
{
@@ -182,7 +188,7 @@ public virtual (string projectDir, string buildOutput) BuildProject(
if (buildOptions.AssertAppBundle)
{
- _provider.AssertWasmSdkBundle(configuration, buildOptions, IsUsingWorkloads, isNativeBuild, res.Output);
+ _provider.AssertWasmSdkBundle(configuration, buildOptions, IsUsingWorkloads, isNativeBuild, wasmFingerprintDotnetJs, res.Output);
}
return (_projectDir, res.Output);
}
diff --git a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj
index 3fa4dfd85231ab..ac77377d0969c6 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj
+++ b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj
@@ -116,9 +116,6 @@
-
-
-
diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs
index fd81105cb77629..c24aa3a563e58b 100644
--- a/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/WasmSdkBasedProjectProvider.cs
@@ -90,7 +90,7 @@ public NativeFilesType GetExpectedFileType(Configuration config, bool isAOT, boo
(config == Configuration.Release) ? NativeFilesType.Relinked :
NativeFilesType.FromRuntimePack;
- public void AssertBundle(Configuration config, MSBuildOptions buildOptions, bool isUsingWorkloads, bool? isNativeBuild = null)
+ public void AssertBundle(Configuration config, MSBuildOptions buildOptions, bool isUsingWorkloads, bool? isNativeBuild = null, bool? wasmFingerprintDotnetJs = null)
{
string frameworkDir = string.IsNullOrEmpty(buildOptions.NonDefaultFrameworkDir) ?
GetBinFrameworkDir(config, buildOptions.IsPublish, _defaultTargetFramework) :
@@ -103,7 +103,8 @@ public void AssertBundle(Configuration config, MSBuildOptions buildOptions, bool
BinFrameworkDir: frameworkDir,
ExpectSymbolsFile: true,
AssertIcuAssets: true,
- AssertSymbolsFile: false
+ AssertSymbolsFile: false,
+ ExpectDotnetJsFingerprinting: wasmFingerprintDotnetJs
));
}
@@ -172,14 +173,14 @@ private void AssertBundle(AssertBundleOptions assertOptions)
}
}
- public void AssertWasmSdkBundle(Configuration config, MSBuildOptions buildOptions, bool isUsingWorkloads, bool? isNativeBuild = null, string? buildOutput = null)
+ public void AssertWasmSdkBundle(Configuration config, MSBuildOptions buildOptions, bool isUsingWorkloads, bool? isNativeBuild = null, bool? wasmFingerprintDotnetJs = null, string? buildOutput = null)
{
if (isUsingWorkloads && buildOutput is not null)
{
// In no-workload case, the path would be from a restored nuget
ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildOptions.TargetFramework ?? _defaultTargetFramework, buildOptions.RuntimeType);
}
- AssertBundle(config, buildOptions, isUsingWorkloads, isNativeBuild);
+ AssertBundle(config, buildOptions, isUsingWorkloads, isNativeBuild, wasmFingerprintDotnetJs);
}
public BuildPaths GetBuildPaths(Configuration configuration, bool forPublish)