From b13f49ad339ebc14840e315f44ea7e99c55549a1 Mon Sep 17 00:00:00 2001
From: Ankit Jain <radical@gmail.com>
Date: Thu, 3 Aug 2023 12:58:00 -0400
Subject: [PATCH 1/2] [wasm] WBT: Use project ids that are safe for use as
 identifiers

For every test project, a random id is used which is
`Path.GetRandomFileName()`. In some cases this `id` gets used in a
generated C/C# source file, and that can cause failures.

For example the following fails with:

```
blz_checkfingerprinting_Release_zqkzgkui.ref/Program.cs(3,48): error CS1001: Identifier expected [/root/helix/work/workitem/e/wbt/blz_checkfingerprinting_Release_zqkzgkui.ref/blz_checkfingerprinting_Release_zqkzgkui.ref.csproj]
blz_checkfingerprinting_Release_zqkzgkui.ref/Program.cs(3,48): error CS1002: ; expected [/root/helix/work/workitem/e/wbt/blz_checkfingerprinting_Release_zqkzgkui.ref/blz_checkfingerprinting_Release_zqkzgkui.ref.csproj]
blz_checkfingerprinting_Release_zqkzgkui.ref/Program.cs(3,51): error CS1031: Type expected [/root/helix/work/workitem/e/wbt/blz_checkfingerprinting_Release_zqkzgkui.ref/blz_checkfingerprinting_Release_zqkzgkui.ref.csproj]
```

because the id, `blz_checkfingerprinting_Release_zqkzgkui.ref`, was used
as a namespace (line 3).

```
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using blz_checkfingerprinting_Release_zqkzgkui.ref;
```

Fix up the generated random ids to make them safer. The code is taken
from `WasmAppBuilder/ManagedToNativeGenerator.cs`.

Fixes https://github.com/dotnet/runtime/issues/86533 .
---
 .../Blazor/AppsettingsTests.cs                |  2 +-
 .../Blazor/BuildPublishTests.cs               | 14 ++++-----
 .../Wasm.Build.Tests/Blazor/CleanTests.cs     |  4 +--
 .../wasm/Wasm.Build.Tests/Blazor/MiscTests.cs |  4 +--
 .../Wasm.Build.Tests/Blazor/MiscTests2.cs     |  2 +-
 .../Wasm.Build.Tests/Blazor/NativeRefTests.cs |  6 ++--
 .../Blazor/NoopNativeRebuildTest.cs           |  4 +--
 .../Blazor/SimpleMultiThreadedTests.cs        |  4 +--
 .../wasm/Wasm.Build.Tests/BuildTestBase.cs    | 31 +++++++++++++++++++
 .../Common/HelperExtensions.cs                |  4 +--
 .../NonWasmTemplateBuildTests.cs              |  2 +-
 .../Templates/NativeBuildTests.cs             |  4 +--
 .../Templates/WasmTemplateTests.cs            | 14 ++++-----
 .../TestAppScenarios/AppTestBase.cs           |  2 +-
 .../WasmNativeDefaultsTests.cs                |  2 +-
 .../wasm/Wasm.Build.Tests/WasmSIMDTests.cs    |  2 +-
 16 files changed, 66 insertions(+), 35 deletions(-)

diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs
index 0304d9f113c70a..8069ef424f1895 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs
@@ -21,7 +21,7 @@ public AppsettingsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture
     [Fact]
     public async Task FileInVfs()
     {
-        string id = $"blazor_{Path.GetRandomFileName()}";
+        string id = $"blazor_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
 
         string projectDirectory = Path.GetDirectoryName(projectFile)!;
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
index 011abb14fb4fe9..9313a9cc70bea0 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
@@ -27,7 +27,7 @@ public BuildPublishTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur
     [InlineData("Release")]
     public async Task DefaultTemplate_WithoutWorkload(string config)
     {
-        string id = $"blz_no_workload_{config}_{Path.GetRandomFileName()}_{s_unicodeChar}";
+        string id = $"blz_no_workload_{config}_{GetRandomId()}_{s_unicodeChar}";
         CreateBlazorWasmTemplateProject(id);
 
         BlazorBuild(new BlazorBuildOptions(id, config));
@@ -45,8 +45,8 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
         // disable relinking tests for Unicode: github.com/emscripten-core/emscripten/issues/17817
         // [ActiveIssue("https://github.com/dotnet/runtime/issues/83497")]
         string id = config == "Release" ?
-            $"blz_no_aot_{config}_{Path.GetRandomFileName()}" :
-            $"blz_no_aot_{config}_{Path.GetRandomFileName()}_{s_unicodeChar}";
+            $"blz_no_aot_{config}_{GetRandomId()}" :
+            $"blz_no_aot_{config}_{GetRandomId()}_{s_unicodeChar}";
         CreateBlazorWasmTemplateProject(id);
 
         BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
@@ -68,7 +68,7 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
     [InlineData("Release", true)]
     public void DefaultTemplate_CheckFingerprinting(string config, bool expectFingerprintOnDotnetJs)
     {
-        string id = $"blz_checkfingerprinting_{config}_{Path.GetRandomFileName()}";
+        string id = $"blz_checkfingerprinting_{config}_{GetRandomId()}";
 
         CreateBlazorWasmTemplateProject(id);
 
@@ -172,7 +172,7 @@ async Task TestDllImport(IPage page)
     [Fact]
     public void BugRegression_60479_WithRazorClassLib()
     {
-        string id = $"blz_razor_lib_top_{Path.GetRandomFileName()}";
+        string id = $"blz_razor_lib_top_{GetRandomId()}";
         InitBlazorWasmProjectDir(id);
 
         string wasmProjectDir = Path.Combine(_projectDir!, "wasm");
@@ -227,7 +227,7 @@ public void BugRegression_60479_WithRazorClassLib()
     [InlineData("Release")]
     public async Task BlazorBuildRunTest(string config)
     {
-        string id = $"blazor_{config}_{Path.GetRandomFileName()}";
+        string id = $"blazor_{config}_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
 
         BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack));
@@ -241,7 +241,7 @@ public async Task BlazorBuildRunTest(string config)
     [InlineData("Release", true)]
     public async Task BlazorPublishRunTest(string config, bool aot)
     {
-        string id = $"blazor_{config}_{Path.GetRandomFileName()}";
+        string id = $"blazor_{config}_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
         if (aot)
             AddItemsPropertiesToProject(projectFile, "<RunAOTCompilation>true</RunAOTCompilation>");
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/CleanTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/CleanTests.cs
index 97595530b6e960..db3c7da2243ac0 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/CleanTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/CleanTests.cs
@@ -25,7 +25,7 @@ public CleanTests(ITestOutputHelper output, SharedBuildPerTestClassFixture build
     [InlineData("Release")]
     public void Blazor_BuildThenClean_NativeRelinking(string config)
     {
-        string id = Path.GetRandomFileName();
+        string id = GetRandomId();
 
         InitBlazorWasmProjectDir(id);
         string projectFile = CreateBlazorWasmTemplateProject(id);
@@ -63,7 +63,7 @@ public void Blazor_BuildNative_ThenBuildNonNative_ThenClean(string config)
 
     private void Blazor_BuildNativeNonNative_ThenCleanTest(string config, bool firstBuildNative)
     {
-        string id = Path.GetRandomFileName();
+        string id = GetRandomId();
 
         InitBlazorWasmProjectDir(id);
         string projectFile = CreateBlazorWasmTemplateProject(id);
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
index c1e2eae553b156..e01a9f4f3e6428 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests.cs
@@ -24,7 +24,7 @@ public MiscTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildC
     [InlineData("Release", false)]
     public void NativeBuild_WithDeployOnBuild_UsedByVS(string config, bool nativeRelink)
     {
-        string id = $"blz_deploy_on_build_{config}_{nativeRelink}_{Path.GetRandomFileName()}";
+        string id = $"blz_deploy_on_build_{config}_{nativeRelink}_{GetRandomId()}";
         string projectFile = CreateProjectWithNativeReference(id);
         string extraProperties = config == "Debug"
                                     ? ("<EmccLinkOptimizationFlag>-O1</EmccLinkOptimizationFlag>" +
@@ -57,7 +57,7 @@ public void NativeBuild_WithDeployOnBuild_UsedByVS(string config, bool nativeRel
     [InlineData("Release")]
     public void DefaultTemplate_AOT_InProjectFile(string config)
     {
-        string id = $"blz_aot_prj_file_{config}_{Path.GetRandomFileName()}";
+        string id = $"blz_aot_prj_file_{config}_{GetRandomId()}";
         string projectFile = CreateBlazorWasmTemplateProject(id);
 
         string extraProperties = config == "Debug"
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
index 3f21ce1dc91444..23c002b454d91c 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
@@ -51,7 +51,7 @@ public void AOT_And_NativeRef_FailBecauseTheyRequireWorkload(string config)
 
     private CommandResult PublishForRequiresWorkloadTest(string config, string extraItems="", string extraProperties="")
     {
-        string id = $"needs_workload_{config}_{Path.GetRandomFileName()}";
+        string id = $"needs_workload_{config}_{GetRandomId()}";
         CreateBlazorWasmTemplateProject(id);
 
         AddItemsPropertiesToProject(Path.Combine(_projectDir!, $"{id}.csproj"),
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/NativeRefTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/NativeRefTests.cs
index 402b920946f5aa..645aab3ac0eb85 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/NativeRefTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/NativeRefTests.cs
@@ -23,7 +23,7 @@ public NativeTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buil
     [ActiveIssue("https://github.com/dotnet/runtime/issues/82725")]
     public void WithNativeReference_AOTInProjectFile(string config)
     {
-        string id = $"blz_nativeref_aot_{config}_{Path.GetRandomFileName()}";
+        string id = $"blz_nativeref_aot_{config}_{GetRandomId()}";
         string projectFile = CreateProjectWithNativeReference(id);
         string extraProperties = config == "Debug"
                                     ? ("<EmccLinkOptimizationFlag>-O1</EmccLinkOptimizationFlag>" +
@@ -45,7 +45,7 @@ public void WithNativeReference_AOTInProjectFile(string config)
     [ActiveIssue("https://github.com/dotnet/runtime/issues/82725")]
     public void WithNativeReference_AOTOnCommandLine(string config)
     {
-        string id = $"blz_nativeref_aot_{config}_{Path.GetRandomFileName()}";
+        string id = $"blz_nativeref_aot_{config}_{GetRandomId()}";
         string projectFile = CreateProjectWithNativeReference(id);
         string extraProperties = config == "Debug"
                                     ? ("<EmccLinkOptimizationFlag>-O1</EmccLinkOptimizationFlag>" +
@@ -66,7 +66,7 @@ public void WithNativeReference_AOTOnCommandLine(string config)
     [InlineData("Release")]
     public void BlazorWasm_CanRunMonoAOTCross_WithNoTrimming(string config)
     {
-        string id = $"blazorwasm_{config}_aot_{Path.GetRandomFileName()}";
+        string id = $"blazorwasm_{config}_aot_{GetRandomId()}";
         CreateBlazorWasmTemplateProject(id);
 
         // We don't want to emcc compile, and link ~180 assemblies!
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/NoopNativeRebuildTest.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/NoopNativeRebuildTest.cs
index e85e235b674155..942d88643df473 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/NoopNativeRebuildTest.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/NoopNativeRebuildTest.cs
@@ -23,7 +23,7 @@ public NoopNativeRebuildTest(ITestOutputHelper output, SharedBuildPerTestClassFi
         [InlineData("Release")]
         public void BlazorNoopRebuild(string config)
         {
-            string id = $"blz_rebuild_{config}_{Path.GetRandomFileName()}";
+            string id = $"blz_rebuild_{config}_{GetRandomId()}";
             string projectFile = CreateBlazorWasmTemplateProject(id);
             AddItemsPropertiesToProject(projectFile, extraProperties: "<WasmBuildNative>true</WasmBuildNative>");
 
@@ -50,7 +50,7 @@ public void BlazorNoopRebuild(string config)
         [InlineData("Release")]
         public void BlazorOnlyLinkRebuild(string config)
         {
-            string id = $"blz_relink_{config}_{Path.GetRandomFileName()}";
+            string id = $"blz_relink_{config}_{GetRandomId()}";
             string projectFile = CreateBlazorWasmTemplateProject(id);
             AddItemsPropertiesToProject(projectFile, extraProperties: "<WasmBuildNative>true</WasmBuildNative>");
 
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs
index f430c235a12fbc..2815259aa9849e 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs
@@ -26,7 +26,7 @@ public SimpleMultiThreadedTests(ITestOutputHelper output, SharedBuildPerTestClas
     // [InlineData("Release")]
     // public async Task BlazorBuildRunTest(string config)
     // {
-    //     string id = $"blazor_mt_{config}_{Path.GetRandomFileName()}";
+    //     string id = $"blazor_mt_{config}_{GetRandomId()}";
     //     string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
 
     //     AddItemsPropertiesToProject(projectFile, "<WasmEnableThreads>true</WasmEnableThreads>");
@@ -44,7 +44,7 @@ public SimpleMultiThreadedTests(ITestOutputHelper output, SharedBuildPerTestClas
     // [InlineData("Release", true)]
     public async Task BlazorPublishRunTest(string config, bool aot)
     {
-        string id = $"blazor_mt_{config}_{Path.GetRandomFileName()}";
+        string id = $"blazor_mt_{config}_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "blazorwasm");
         AddItemsPropertiesToProject(projectFile, "<WasmEnableThreads>true</WasmEnableThreads>");
         // if (aot)
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
index 603b2cc4778dae..02b5be8887aca9 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
@@ -38,6 +38,7 @@ public abstract class BuildTestBase : IClassFixture<SharedBuildPerTestClassFixtu
         protected string _nugetPackagesDir = string.Empty;
         private ProjectProviderBase _providerOfBaseType;
 
+        private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' };
         private static bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
         // changing Windows's language programistically is complicated and Node is using OS's language to determine
         // what is client's preferred locale and then to load corresponding ICU => skip automatic icu testing with Node
@@ -575,6 +576,36 @@ public void Dispose()
                 _buildContext.RemoveFromCache(_projectDir, keepDir: s_skipProjectCleanup);
         }
 
+        public static string GetRandomId() => FixupSymbolName(Path.GetRandomFileName());
+
+        public static string FixupSymbolName(string name)
+        {
+            UTF8Encoding utf8 = new();
+            byte[] bytes = utf8.GetBytes(name);
+            StringBuilder sb = new();
+
+            foreach (byte b in bytes)
+            {
+                if ((b >= (byte)'0' && b <= (byte)'9') ||
+                    (b >= (byte)'a' && b <= (byte)'z') ||
+                    (b >= (byte)'A' && b <= (byte)'Z') ||
+                    (b == (byte)'_'))
+                {
+                    sb.Append((char)b);
+                }
+                else if (s_charsToReplace.Contains((char)b))
+                {
+                    sb.Append('_');
+                }
+                else
+                {
+                    sb.Append($"_{b:X}_");
+                }
+            }
+
+            return sb.ToString();
+        }
+
         internal BuildPaths GetBuildPaths(BuildArgs buildArgs, bool forPublish = true)
         {
             string objDir = GetObjDir(buildArgs.Config);
diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/HelperExtensions.cs b/src/mono/wasm/Wasm.Build.Tests/Common/HelperExtensions.cs
index 7690ce61b88052..35023c6174c2f9 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Common/HelperExtensions.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Common/HelperExtensions.cs
@@ -93,11 +93,11 @@ public static class HelperExtensions
         {
             IEnumerable<object?> hostsEnumerable = hosts.Enumerate();
             if (hosts == RunHost.None)
-                return data.Select(d => d.Append((object?) Path.GetRandomFileName()));
+                return data.Select(d => d.Append((object?) BuildTestBase.GetRandomId()));
 
             return data.SelectMany(d =>
             {
-                string runId = Path.GetRandomFileName();
+                string runId = BuildTestBase.GetRandomId();
                 return hostsEnumerable.Select(o =>
                         d.Append((object?)o)
                          .Append((object?)runId));
diff --git a/src/mono/wasm/Wasm.Build.Tests/NonWasmTemplateBuildTests.cs b/src/mono/wasm/Wasm.Build.Tests/NonWasmTemplateBuildTests.cs
index c160dec642ac1b..2b48af5d7f8905 100644
--- a/src/mono/wasm/Wasm.Build.Tests/NonWasmTemplateBuildTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/NonWasmTemplateBuildTests.cs
@@ -98,7 +98,7 @@ private void NonWasmConsoleBuild(string config,
                                      string? directoryBuildTargets = null,
                                      bool shouldRun = true)
     {
-        string id = $"nonwasm_{targetFramework}_{config}_{Path.GetRandomFileName()}";
+        string id = $"nonwasm_{targetFramework}_{config}_{GetRandomId()}";
         InitPaths(id);
         InitProjectDir(_projectDir);
 
diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs
index f9dc1f450f643e..37f9b6aa46ca25 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Templates/NativeBuildTests.cs
@@ -22,7 +22,7 @@ public NativeBuildTests(ITestOutputHelper output, SharedBuildPerTestClassFixture
         [InlineData(false)]
         public void BuildWithUndefinedNativeSymbol(bool allowUndefined)
         {
-            string id = $"UndefinedNativeSymbol_{(allowUndefined ? "allowed" : "disabled")}_{Path.GetRandomFileName()}";
+            string id = $"UndefinedNativeSymbol_{(allowUndefined ? "allowed" : "disabled")}_{GetRandomId()}";
 
             string code = @"
                 using System;
@@ -67,7 +67,7 @@ public void BuildWithUndefinedNativeSymbol(bool allowUndefined)
         [InlineData("Release")]
         public void ProjectWithDllImportsRequiringMarshalIlGen_ArrayTypeParameter(string config)
         {
-            string id = $"dllimport_incompatible_{Path.GetRandomFileName()}";
+            string id = $"dllimport_incompatible_{GetRandomId()}";
             string projectPath = CreateWasmTemplateProject(id, template: "wasmconsole");
 
             string nativeSourceFilename = "incompatible_type.c";
diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs
index 2e698c3fe880d8..0688948f84d676 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs
@@ -86,7 +86,7 @@ private void UpdateMainJsEnvironmentVariables(params (string key, string value)[
         [InlineData("Release")]
         public void BrowserBuildThenPublish(string config)
         {
-            string id = $"browser_{config}_{Path.GetRandomFileName()}";
+            string id = $"browser_{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmbrowser");
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
@@ -131,7 +131,7 @@ public void BrowserBuildThenPublish(string config)
         [InlineData("Release")]
         public void ConsoleBuildThenPublish(string config)
         {
-            string id = $"{config}_{Path.GetRandomFileName()}";
+            string id = $"{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
@@ -196,7 +196,7 @@ public void ConsoleBuildAndRunForSpecificTFM(string config, string extraNewArgs,
 
         private void ConsoleBuildAndRun(string config, bool relinking, string extraNewArgs, string expectedTFM)
         {
-            string id = $"{config}_{Path.GetRandomFileName()}";
+            string id = $"{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole", extraNewArgs);
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
@@ -262,7 +262,7 @@ public async Task RunWithDifferentAppBundleLocations(bool forConsole, bool runOu
 
         private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false)
         {
-            string id = $"browser_{config}_{Path.GetRandomFileName()}";
+            string id = $"browser_{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmbrowser");
 
             UpdateBrowserMainJs(DefaultTargetFramework);
@@ -295,7 +295,7 @@ private async Task BrowserRunTwiceWithAndThenWithoutBuildAsync(string config, st
 
         private Task ConsoleRunWithAndThenWithoutBuildAsync(string config, string extraProperties = "", bool runOutsideProjectDirectory = false)
         {
-            string id = $"console_{config}_{Path.GetRandomFileName()}";
+            string id = $"console_{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
 
             UpdateProgramCS();
@@ -358,7 +358,7 @@ public static TheoryData<string, bool, bool> TestDataForConsolePublishAndRun()
         [MemberData(nameof(TestDataForConsolePublishAndRun))]
         public void ConsolePublishAndRun(string config, bool aot, bool relinking)
         {
-            string id = $"{config}_{Path.GetRandomFileName()}";
+            string id = $"{config}_{GetRandomId()}";
             string projectFile = CreateWasmTemplateProject(id, "wasmconsole");
             string projectName = Path.GetFileNameWithoutExtension(projectFile);
 
@@ -416,7 +416,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking)
         public async Task BrowserBuildAndRun(string extraNewArgs, string targetFramework, string runtimeAssetsRelativePath)
         {
             string config = "Debug";
-            string id = $"browser_{config}_{Path.GetRandomFileName()}";
+            string id = $"browser_{config}_{GetRandomId()}";
             CreateWasmTemplateProject(id, "wasmbrowser", extraNewArgs);
 
             UpdateBrowserMainJs(targetFramework, runtimeAssetsRelativePath);
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
index faef773ca8cb35..444d70228b08fa 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
@@ -25,7 +25,7 @@ protected AppTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture b
 
     protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix = null)
     {
-        Id = $"{generatedProjectNamePrefix ?? assetName}_{Path.GetRandomFileName()}";
+        Id = $"{generatedProjectNamePrefix ?? assetName}_{GetRandomId()}";
         InitBlazorWasmProjectDir(Id);
 
         LogPath = Path.Combine(s_buildEnv.LogRootPath, Id);
diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs
index 7b6389014230e5..3e30da43d9655e 100644
--- a/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/WasmNativeDefaultsTests.cs
@@ -93,7 +93,7 @@ private string CheckWasmNativeDefaultValue(string projectName,
                                         insertAtEnd: printValueTarget);
 
             (_, string output) = BuildProject(buildArgs,
-                                                id: Path.GetRandomFileName(),
+                                                id: GetRandomId(),
                                                 new BuildProjectOptions(
                                                     InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42),
                                                     DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack,
diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs
index de1a5683138ab8..b63098064f166e 100644
--- a/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/WasmSIMDTests.cs
@@ -107,7 +107,7 @@ public void PublishWithoutSIMD_AOT(BuildArgs buildArgs, RunHost host, string id)
         [InlineData("Release", /*aot*/false, /*publish*/true)]
         public void BuildWithSIMDNeedsWorkload(string config, bool aot, bool publish)
         {
-            string id = Path.GetRandomFileName();
+            string id = GetRandomId();
             string projectName = $"simd_no_workload_{config}_aot_{aot}";
             BuildArgs buildArgs = new
             (

From 84ce605e92f7f69a9c504e6aed71d85003137419 Mon Sep 17 00:00:00 2001
From: Ankit Jain <radical@gmail.com>
Date: Thu, 3 Aug 2023 13:11:54 -0400
Subject: [PATCH 2/2] Apply the same for wasi

---
 .../wasi/Wasi.Build.Tests/BuildTestBase.cs    |  2 ++
 .../Wasi.Build.Tests/WasiTemplateTests.cs     |  4 +--
 .../wasm/Wasm.Build.Tests/BuildTestBase.cs    | 30 +------------------
 .../wasm/Wasm.Build.Tests/Common/TestUtils.cs | 30 +++++++++++++++++++
 4 files changed, 35 insertions(+), 31 deletions(-)

diff --git a/src/mono/wasi/Wasi.Build.Tests/BuildTestBase.cs b/src/mono/wasi/Wasi.Build.Tests/BuildTestBase.cs
index 44a764ead77863..9df5fcbf9d2dd5 100644
--- a/src/mono/wasi/Wasi.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasi/Wasi.Build.Tests/BuildTestBase.cs
@@ -637,6 +637,8 @@ public void Dispose()
                 _buildContext.RemoveFromCache(_projectDir, keepDir: s_skipProjectCleanup);
         }
 
+        public static string GetRandomId() => TestUtils.FixupSymbolName(Path.GetRandomFileName());
+
         private static string GetEnvironmentVariableOrDefault(string envVarName, string defaultValue)
         {
             string? value = Environment.GetEnvironmentVariable(envVarName);
diff --git a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs
index 196d9305d1f25a..85f7bacf6fcea1 100644
--- a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs
+++ b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs
@@ -25,7 +25,7 @@ public WasiTemplateTests(ITestOutputHelper output, SharedBuildPerTestClassFixtur
     [InlineData("Release")]
     public void ConsoleBuildThenPublish(string config)
     {
-        string id = $"{config}_{Path.GetRandomFileName()}";
+        string id = $"{config}_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "wasiconsole");
         string projectName = Path.GetFileNameWithoutExtension(projectFile);
         File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_simpleMainWithArgs);
@@ -88,7 +88,7 @@ public static TheoryData<string, bool, bool> TestDataForConsolePublishAndRun()
     [MemberData(nameof(TestDataForConsolePublishAndRun))]
     public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinking, bool invariantTimezone)
     {
-        string id = $"{config}_{Path.GetRandomFileName()}";
+        string id = $"{config}_{GetRandomId()}";
         string projectFile = CreateWasmTemplateProject(id, "wasiconsole");
         string projectName = Path.GetFileNameWithoutExtension(projectFile);
         File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_simpleMainWithArgs);
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
index 02b5be8887aca9..fa15c7bef6d817 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
@@ -576,35 +576,7 @@ public void Dispose()
                 _buildContext.RemoveFromCache(_projectDir, keepDir: s_skipProjectCleanup);
         }
 
-        public static string GetRandomId() => FixupSymbolName(Path.GetRandomFileName());
-
-        public static string FixupSymbolName(string name)
-        {
-            UTF8Encoding utf8 = new();
-            byte[] bytes = utf8.GetBytes(name);
-            StringBuilder sb = new();
-
-            foreach (byte b in bytes)
-            {
-                if ((b >= (byte)'0' && b <= (byte)'9') ||
-                    (b >= (byte)'a' && b <= (byte)'z') ||
-                    (b >= (byte)'A' && b <= (byte)'Z') ||
-                    (b == (byte)'_'))
-                {
-                    sb.Append((char)b);
-                }
-                else if (s_charsToReplace.Contains((char)b))
-                {
-                    sb.Append('_');
-                }
-                else
-                {
-                    sb.Append($"_{b:X}_");
-                }
-            }
-
-            return sb.ToString();
-        }
+        public static string GetRandomId() => TestUtils.FixupSymbolName(Path.GetRandomFileName());
 
         internal BuildPaths GetBuildPaths(BuildArgs buildArgs, bool forPublish = true)
         {
diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
index 5bb367592658da..d2991f5a094837 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Common/TestUtils.cs
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Text;
 using Xunit;
 using Xunit.Sdk;
 
@@ -82,4 +83,33 @@ public static void AssertEqual(object expected, object actual, string label)
             expected, actual,
             $"[{label}]\n");
     }
+
+    private static readonly char[] s_charsToReplace = new[] { '.', '-', '+' };
+    public static string FixupSymbolName(string name)
+    {
+        UTF8Encoding utf8 = new();
+        byte[] bytes = utf8.GetBytes(name);
+        StringBuilder sb = new();
+
+        foreach (byte b in bytes)
+        {
+            if ((b >= (byte)'0' && b <= (byte)'9') ||
+                (b >= (byte)'a' && b <= (byte)'z') ||
+                (b >= (byte)'A' && b <= (byte)'Z') ||
+                (b == (byte)'_'))
+            {
+                sb.Append((char)b);
+            }
+            else if (s_charsToReplace.Contains((char)b))
+            {
+                sb.Append('_');
+            }
+            else
+            {
+                sb.Append($"_{b:X}_");
+            }
+        }
+
+        return sb.ToString();
+    }
 }
