PATENTS.TXT
THIRD-PARTY-NOTICES.TXT
src/workloads/*
+ src/mono/wasm/sln/*
]
jobs:
<Output TaskParameter="Items" ItemName="_WasmOutputWithHash" />
</GetFileHash>
-
-
<GenerateWasmBootJson
AssemblyPath="@(IntermediateAssembly)"
Resources="@(_WasmOutputWithHash)"
string ProjectFileContents,
string? ExtraBuildArgs);
public record BuildProduct(string ProjectDir, string LogFile, bool Result);
- internal record FileStat (bool Exists, DateTime LastWriteTimeUtc, long Length, string FullPath);
- internal record BuildPaths(string ObjWasmDir, string ObjDir, string BinDir, string BundleDir);
public record BuildProjectOptions
(
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable enable
-
-namespace Wasm.Build.Tests;
-
-public record AssertTestMainJsAppBundleOptions
-(
- string BundleDir,
- string ProjectName,
- string Config,
- string MainJS,
- bool HasV8Script,
- GlobalizationMode? GlobalizationMode,
- string PredefinedIcudt = "",
- bool UseWebcil = true,
- bool IsBrowserProject = true,
- bool IsPublish = false
-);
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+
+// Identical to AssertBundleOptionsBase currently
+public record AssertWasmSdkBundleOptions(
+ string Config,
+ bool IsPublish,
+ string TargetFramework,
+ string BinFrameworkDir,
+ string? PredefinedIcudt,
+ GlobalizationMode GlobalizationMode = GlobalizationMode.Default,
+ string BootJsonFileName = "blazor.boot.json",
+ NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack,
+ RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded,
+ bool ExpectFingerprintOnDotnetJs = false,
+ bool ExpectSymbolsFile = true,
+ bool AssertIcuAssets = true,
+ bool AssertSymbolsFile = true)
+ : AssertBundleOptionsBase(
+ Config: Config,
+ IsPublish: IsPublish,
+ TargetFramework: TargetFramework,
+ BinFrameworkDir: BinFrameworkDir,
+ PredefinedIcudt: PredefinedIcudt,
+ GlobalizationMode: GlobalizationMode,
+ ExpectedFileType: ExpectedFileType,
+ RuntimeType: RuntimeType,
+ BootJsonFileName: BootJsonFileName,
+ ExpectFingerprintOnDotnetJs: ExpectFingerprintOnDotnetJs,
+ ExpectSymbolsFile: ExpectSymbolsFile,
+ AssertIcuAssets: AssertIcuAssets,
+ AssertSymbolsFile: AssertSymbolsFile)
+{}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+
+public record BlazorBuildOptions
+(
+ string Id,
+ string Config,
+ NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack,
+ string TargetFramework = BuildTestBase.DefaultTargetFrameworkForBlazor,
+ bool IsPublish = false,
+ bool WarnAsError = true,
+ bool ExpectRelinkDirWhenPublishing = false,
+ bool ExpectFingerprintOnDotnetJs = false,
+ RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded
+);
// 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.Data;
-using System.IO;
-using System.Linq;
-using Xunit;
using Xunit.Abstractions;
-using System.Runtime.Serialization.Json;
-using Microsoft.NET.Sdk.WebAssembly;
#nullable enable
: base(_testOutput, _projectDir)
{}
- public void AssertBlazorBootJson(
- string config,
- bool isPublish,
- string targetFramework = BuildTestBase.DefaultTargetFrameworkForBlazor,
- bool expectFingerprintOnDotnetJs = false,
- RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded)
- {
- AssertBootJson(binFrameworkDir: FindBlazorBinFrameworkDir(config, isPublish, targetFramework),
- isPublish: isPublish,
- expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
- runtimeType: runtimeType);
- }
-
- public void AssertBlazorBundle(
- BlazorBuildOptions options,
- bool isPublish,
- string? binFrameworkDir = null)
- {
- EnsureProjectDirIsSet();
- if (options.TargetFramework is null)
- options = options with { TargetFramework = BuildTestBase.DefaultTargetFrameworkForBlazor };
-
- AssertDotNetNativeFiles(options.ExpectedFileType,
- options.Config,
- forPublish: isPublish,
- targetFramework: options.TargetFramework,
- expectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs,
- runtimeType: options.RuntimeType);
-
- AssertBlazorBootJson(config: options.Config,
- isPublish: isPublish,
- targetFramework: options.TargetFramework,
- expectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs,
- runtimeType: options.RuntimeType);
- }
+ public void AssertBundle(BlazorBuildOptions options)
+ => AssertBundle(new AssertWasmSdkBundleOptions(
+ Config: options.Config,
+ IsPublish: options.IsPublish,
+ TargetFramework: options.TargetFramework,
+ BinFrameworkDir: FindBinFrameworkDir(options.Config, options.IsPublish, options.TargetFramework),
+ GlobalizationMode: GlobalizationMode.Default,
+ PredefinedIcudt: null,
+ ExpectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs,
+ ExpectedFileType: options.ExpectedFileType,
+ RuntimeType: options.RuntimeType,
+ AssertIcuAssets: false, // FIXME: this is broken right now
+ AssertSymbolsFile: false // FIXME: not supported yet
+ ));
}
public abstract class BlazorWasmTestBase : WasmTemplateTestBase
{
- protected BlazorWasmProjectProvider _provider;
+ protected readonly BlazorWasmProjectProvider _provider;
protected BlazorWasmTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
: base(output, buildContext, new BlazorWasmProjectProvider(output))
{
_provider = GetProvider<BlazorWasmProjectProvider>();
+ _provider.BundleDirName = "wwwroot";
}
public void InitBlazorWasmProjectDir(string id, string targetFramework = DefaultTargetFrameworkForBlazor)
.ExecuteWithCapturedOutput("new blazorwasm")
.EnsureSuccessful();
- string projectFile = Path.Combine(_projectDir!, $"{id}.csproj");
- if (!UseWebcil)
- AddItemsPropertiesToProject(projectFile, "<WasmEnableWebcil>false</WasmEnableWebcil>");
- return projectFile;
+ return Path.Combine(_projectDir!, $"{id}.csproj");
}
protected (CommandResult, string) BlazorBuild(BlazorBuildOptions options, params string[] extraArgs)
if (options.WarnAsError)
extraArgs = extraArgs.Append("/warnaserror").ToArray();
- var res = BlazorBuildInternal(options.Id, options.Config, publish: false, setWasmDevel: false, extraArgs);
- _provider.AssertBlazorBundle(options, isPublish: false);
+ (CommandResult res, string logPath) = BlazorBuildInternal(options.Id, options.Config, publish: false, setWasmDevel: false, extraArgs);
+
+ AssertBundle(res.Output, options with { IsPublish = false });
- return res;
+ return (res, logPath);
}
protected (CommandResult, string) BlazorPublish(BlazorBuildOptions options, params string[] extraArgs)
{
- var res = BlazorBuildInternal(options.Id, options.Config, publish: true, setWasmDevel: false, extraArgs);
- _provider.AssertBlazorBundle(options, isPublish: true);
+ if (options.WarnAsError)
+ extraArgs = extraArgs.Append("/warnaserror").ToArray();
+
+ (CommandResult res, string logPath) = BlazorBuildInternal(options.Id, options.Config, publish: true, setWasmDevel: false, extraArgs);
+ AssertBundle(res.Output, options with { IsPublish = true });
if (options.ExpectedFileType == NativeFilesType.AOT)
{
// check for this too, so we know the format is correct for the negative
// test for jsinterop.webassembly.dll
- Assert.Contains("Microsoft.JSInterop.dll -> Microsoft.JSInterop.dll.bc", res.Item1.Output);
+ Assert.Contains("Microsoft.JSInterop.dll -> Microsoft.JSInterop.dll.bc", res.Output);
// make sure this assembly gets skipped
- Assert.DoesNotContain("Microsoft.JSInterop.WebAssembly.dll -> Microsoft.JSInterop.WebAssembly.dll.bc", res.Item1.Output);
+ Assert.DoesNotContain("Microsoft.JSInterop.WebAssembly.dll -> Microsoft.JSInterop.WebAssembly.dll.bc", res.Output);
}
- string objBuildDir = Path.Combine(_projectDir!, "obj", options.Config, options.TargetFramework, "wasm", "for-build");
+ string objBuildDir = Path.Combine(_projectDir!, "obj", options.Config, options.TargetFramework!, "wasm", "for-build");
// Check that we linked only for publish
if (options.ExpectRelinkDirWhenPublishing)
Assert.True(Directory.Exists(objBuildDir), $"Could not find expected {objBuildDir}, which gets created when relinking during Build. This is likely a test authoring error");
else
Assert.False(Directory.Exists(objBuildDir), $"Found unexpected {objBuildDir}, which gets created when relinking during Build");
- return res;
+ return (res, logPath);
}
- protected (CommandResult, string) BlazorBuildInternal(string id, string config, bool publish = false, bool setWasmDevel = true, params string[] extraArgs)
+ protected (CommandResult res, string logPath) BlazorBuildInternal(
+ string id,
+ string config,
+ bool publish = false,
+ bool setWasmDevel = true,
+ params string[] extraArgs)
+ => BuildProjectWithoutAssert(
+ id,
+ config,
+ new BuildProjectOptions(CreateProject: false, UseCache: false, Publish: publish),
+ extraArgs.Concat(new[]
+ {
+ "-p:BlazorEnableCompression=false",
+ setWasmDevel ? "-p:_WasmDevel=true" : string.Empty
+ }).ToArray());
+
+ public void AssertBundle(string buildOutput, BlazorBuildOptions blazorBuildOptions)
{
- string label = publish ? "publish" : "build";
- _testOutput.WriteLine($"{Environment.NewLine}** {label} **{Environment.NewLine}");
-
- string logPath = Path.Combine(s_buildEnv.LogRootPath, id, $"{id}-{label}.binlog");
- string[] combinedArgs = new[]
+ if (IsUsingWorkloads)
{
- label, // same as the command name
- $"-bl:{logPath}",
- $"-p:Configuration={config}",
- !UseWebcil ? "-p:WasmEnableWebcil=false" : string.Empty,
- "-p:BlazorEnableCompression=false",
- "-nr:false",
- setWasmDevel ? "-p:_WasmDevel=true" : string.Empty
- }.Concat(extraArgs).ToArray();
-
- CommandResult res = new DotNetCommand(s_buildEnv, _testOutput)
- .WithWorkingDirectory(_projectDir!)
- .WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir)
- .ExecuteWithCapturedOutput(combinedArgs)
- .EnsureSuccessful();
+ // In no-workload case, the path would be from a restored nuget
+ ProjectProviderBase.AssertRuntimePackPath(buildOutput, blazorBuildOptions.TargetFramework ?? DefaultTargetFramework);
+ }
- return (res, logPath);
+ _provider.AssertBundle(blazorBuildOptions);
}
protected string CreateProjectWithNativeReference(string id)
}
}
+ public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFrameworkForBlazor)
+ => _provider.FindBinFrameworkDir(config: config, forPublish: forPublish, framework: framework);
}
// 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.IO;
using System.Linq;
using System.Text.Json;
-using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
[Theory, TestCategory("no-workload")]
[InlineData("Debug")]
[InlineData("Release")]
- public void DefaultTemplate_WithoutWorkload(string config)
+ public async Task DefaultTemplate_WithoutWorkload(string config)
{
string id = $"blz_no_workload_{config}_{Path.GetRandomFileName()}_{s_unicodeChar}";
CreateBlazorWasmTemplateProject(id);
- // Build
- BlazorBuildInternal(id, config, publish: false);
- _provider.AssertBlazorBootJson(config, isPublish: false);
+ BlazorBuild(new BlazorBuildOptions(id, config));
+ await BlazorRunForBuildWithDotnetRun(config);
- // Publish
- BlazorBuildInternal(id, config, publish: true);
- _provider.AssertBlazorBootJson(config, isPublish: true);
+ BlazorPublish(new BlazorBuildOptions(id, config));
+ await BlazorRunForPublishWithWebServer(config);
}
[Theory]
string oldContent = File.ReadAllText(counterRazorPath);
File.WriteAllText(counterRazorPath, oldContent + additionalCode);
}
-
}
AddItemsPropertiesToProject(projectFile, extraProperties: extraProperties);
// build with -p:DeployOnBuild=true, and that will trigger a publish
- (CommandResult res, _) = BlazorBuildInternal(id, config, publish: false, setWasmDevel: false, "-p:DeployOnBuild=true");
-
- var expectedFileType = nativeRelink ? NativeFilesType.Relinked : NativeFilesType.AOT;
-
- _provider.AssertBlazorBundle(new BlazorBuildOptions
- (
- Id: id,
- Config: config,
- ExpectedFileType: expectedFileType
- ), isPublish: true);
-
- if (expectedFileType == NativeFilesType.AOT)
- {
- // check for this too, so we know the format is correct for the negative
- // test for jsinterop.webassembly.dll
- Assert.Contains("Microsoft.JSInterop.dll -> Microsoft.JSInterop.dll.bc", res.Output);
-
- // make sure this assembly gets skipped
- Assert.DoesNotContain("Microsoft.JSInterop.WebAssembly.dll -> Microsoft.JSInterop.WebAssembly.dll.bc", res.Output);
- }
-
- // Check that we linked only for publish
- string objBuildDir = Path.Combine(_projectDir!, "obj", config, DefaultTargetFramework, "wasm", "for-build");
- Assert.False(Directory.Exists(objBuildDir), $"Found unexpected {objBuildDir}, which gets creating when relinking during Build");
-
- // double check!
+ (CommandResult res, _) = BlazorBuild(new BlazorBuildOptions(
+ Id: id,
+ Config: config,
+ ExpectedFileType: nativeRelink ? NativeFilesType.Relinked : NativeFilesType.AOT,
+ ExpectRelinkDirWhenPublishing: false,
+ IsPublish: false),
+ "-p:DeployBuild=true");
+
+ // double check relinking!
int index = res.Output.IndexOf("pinvoke.c -> pinvoke.o");
Assert.NotEqual(-1, index);
(
Action? InitProject = null,
bool? DotnetWasmFromRuntimePack = null,
- GlobalizationMode? GlobalizationMode = null,
+ GlobalizationMode GlobalizationMode = GlobalizationMode.Default,
string? PredefinedIcudt = null,
bool UseCache = true,
bool ExpectSuccess = true,
bool HasV8Script = true,
string? Verbosity = null,
string? Label = null,
- string? TargetFramework = null,
+ string TargetFramework = BuildTestBase.DefaultTargetFramework,
string? MainJS = null,
bool IsBrowserProject = true,
IDictionary<string, string>? ExtraBuildEnvironmentVariables = null
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using System.Xml;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
-using Microsoft.Playwright;
#nullable enable
_providerOfBaseType = providerBase;
}
- // Meant for special case where we *want* to set it to null,
- // and thus avoid the ArgumentNullException
- // protected void ResetProjectDir() => _providerOfBaseType.ProjectDir = null;
-
public static IEnumerable<IEnumerable<object?>> ConfigWithAOTData(bool aot, string? config = null, string? extraArgs = null)
{
if (extraArgs == null)
}
}
+ public (CommandResult res, string logPath) BuildProjectWithoutAssert(
+ string id,
+ string config,
+ BuildProjectOptions buildProjectOptions,
+ params string[] extraArgs)
+ {
+ string buildType = buildProjectOptions.Publish ? "publish" : "build";
+ string logFileSuffix = buildProjectOptions.Label == null ? string.Empty : buildProjectOptions.Label.Replace(' ', '_') + "-";
+ string logFilePath = Path.Combine(s_buildEnv.LogRootPath, id, $"{id}-{logFileSuffix}{buildType}.binlog");
+
+ _testOutput.WriteLine($"{Environment.NewLine}** -------- {buildType} -------- **{Environment.NewLine}");
+ _testOutput.WriteLine($"Binlog path: {logFilePath}");
+
+ List<string> commandLineArgs = new()
+ {
+ buildType,
+ $"-bl:{logFilePath}",
+ $"-p:Configuration={config}",
+ "-nr:false",
+ !UseWebcil ? "-p:WasmEnableWebcil=false" : string.Empty,
+ };
+ commandLineArgs.AddRange(extraArgs);
+
+ if (buildProjectOptions.Publish && buildProjectOptions.BuildOnlyAfterPublish)
+ commandLineArgs.Append("-p:WasmBuildOnlyAfterPublish=true");
+
+ CommandResult res = new DotNetCommand(s_buildEnv, _testOutput)
+ .WithWorkingDirectory(_projectDir!)
+ .WithEnvironmentVariable("NUGET_PACKAGES", _nugetPackagesDir)
+ .WithEnvironmentVariables(buildProjectOptions.ExtraBuildEnvironmentVariables)
+ .ExecuteWithCapturedOutput(commandLineArgs.ToArray());
+ if (buildProjectOptions.ExpectSuccess)
+ res.EnsureSuccessful();
+ else if (res.ExitCode == 0)
+ throw new XunitException($"Build should have failed, but it didn't. Process exited with exitCode : {res.ExitCode}");
+
+ return (res, logFilePath);
+ }
+
protected string RunAndTestWasmApp(BuildArgs buildArgs,
RunHost host,
string id,
extraProperties += $"\n<EmccVerbose>{s_isWindows}</EmccVerbose>\n";
}
- if (!UseWebcil)
- {
- extraProperties += "<WasmEnableWebcil>false</WasmEnableWebcil>\n";
- }
-
extraItems += "<WasmExtraFilesToDeploy Include='index.html' />";
string projectContents = projectTemplate
return contents.Replace(s_nugetInsertionTag, $@"<add key=""nuget-local"" value=""{localNuGetsPath}"" />");
}
- public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFrameworkForBlazor)
- => new BlazorWasmProjectProvider(_testOutput, _projectDir)
- .FindBlazorBinFrameworkDir(config, forPublish, framework);
-
protected string GetBinDir(string config, string targetFramework = DefaultTargetFramework, string? baseDir = null)
{
var dir = baseDir ?? _projectDir;
_buildContext.RemoveFromCache(_projectDir, keepDir: s_skipProjectCleanup);
}
- private static string GetEnvironmentVariableOrDefault(string envVarName, string defaultValue)
- {
- string? value = Environment.GetEnvironmentVariable(envVarName);
- return string.IsNullOrEmpty(value) ? defaultValue : value;
- }
-
internal BuildPaths GetBuildPaths(BuildArgs buildArgs, bool forPublish = true)
{
string objDir = GetObjDir(buildArgs.Config);
}
}";
- private IHostRunner GetHostRunnerFromRunHost(RunHost host) => host switch
+ private static IHostRunner GetHostRunnerFromRunHost(RunHost host) => host switch
{
RunHost.V8 => new V8HostRunner(),
RunHost.NodeJS => new NodeJSHostRunner(),
string ProjectFileContents,
string? ExtraBuildArgs);
public record BuildProduct(string ProjectDir, string LogFile, bool Result, string BuildOutput);
- public record FileStat(bool Exists, DateTime LastWriteTimeUtc, long Length, string FullPath);
- public record BuildPaths(string ObjWasmDir, string ObjDir, string BinDir, string BundleDir);
-
- public record BlazorBuildOptions
- (
- string Id,
- string Config,
- NativeFilesType ExpectedFileType,
- string TargetFramework = BuildTestBase.DefaultTargetFrameworkForBlazor,
- bool WarnAsError = true,
- bool ExpectRelinkDirWhenPublishing = false,
- bool ExpectFingerprintOnDotnetJs = false,
- RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded
- );
-
- public enum GlobalizationMode
- {
- Invariant, // no icu
- FullIcu, // full icu data: icudt.dat is loaded
- PredefinedIcu, // user set WasmIcuDataFileName value and we are loading that file
- Hybrid // reduced icu, missing data is provided by platform-native functions (web api for wasm)
- };
public enum NativeFilesType { FromRuntimePack, Relinked, AOT };
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+using System.IO;
+
+namespace Wasm.Build.Tests;
+
+public abstract record AssertBundleOptionsBase(
+ string Config,
+ bool IsPublish,
+ string TargetFramework,
+ string BinFrameworkDir,
+ string? PredefinedIcudt,
+ string BundleDirName = "wwwroot",
+ GlobalizationMode GlobalizationMode = GlobalizationMode.Default,
+ string BootJsonFileName = "blazor.boot.json",
+ NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack,
+ RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded,
+ bool ExpectFingerprintOnDotnetJs = false,
+ bool ExpectSymbolsFile = true,
+ bool AssertIcuAssets = true,
+ bool AssertSymbolsFile = true)
+{
+ public bool DotnetWasmFromRuntimePack => ExpectedFileType == NativeFilesType.FromRuntimePack;
+ public bool AOT => ExpectedFileType == NativeFilesType.AOT;
+ public string BundleDir => Path.Combine(BinFrameworkDir, "..");
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+
+public record AssertTestMainJsAppBundleOptions(
+ string Config,
+ bool IsPublish,
+ string TargetFramework,
+ string BinFrameworkDir,
+ string? PredefinedIcudt,
+ string ProjectName,
+ string MainJS,
+ GlobalizationMode GlobalizationMode = GlobalizationMode.Default,
+ string BootJsonFileName = "blazor.boot.json",
+ NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack,
+ RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded,
+ bool ExpectFingerprintOnDotnetJs = false,
+ bool ExpectSymbolsFile = true,
+ bool AssertIcuAssets = true,
+ bool AssertSymbolsFile = true,
+ bool HasV8Script = false,
+ bool IsBrowserProject = true)
+ : AssertBundleOptionsBase(
+ Config: Config,
+ IsPublish: IsPublish,
+ TargetFramework: TargetFramework,
+ BinFrameworkDir: BinFrameworkDir,
+ PredefinedIcudt: PredefinedIcudt,
+ GlobalizationMode: GlobalizationMode,
+ ExpectedFileType: ExpectedFileType,
+ RuntimeType: RuntimeType,
+ BootJsonFileName: BootJsonFileName,
+ ExpectFingerprintOnDotnetJs: ExpectFingerprintOnDotnetJs,
+ ExpectSymbolsFile: ExpectSymbolsFile,
+ AssertIcuAssets: AssertIcuAssets,
+ AssertSymbolsFile: AssertSymbolsFile)
+{
+}
using System;
using System.Collections.Generic;
using System.IO;
-using System.Reflection;
using System.Runtime.InteropServices;
#nullable enable
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+public record BuildPaths(string ObjWasmDir, string ObjDir, string BinDir, string BundleDir);
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+public record FileStat(bool Exists, DateTime LastWriteTimeUtc, long Length, string FullPath);
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
+
+namespace Wasm.Build.Tests;
+public enum GlobalizationMode
+{
+ Default, // chosen based on locale
+ Invariant, // no icu
+ FullIcu, // full icu data: icudt.dat is loaded
+ PredefinedIcu, // user set WasmIcuDataFileName value and we are loading that file
+ Hybrid // reduced icu, missing data is provided by platform-native functions (web api for wasm)
+};
public record XHarnessArgsOptions(string jsRelativePath, string environmentLocale, RunHost host);
-interface IHostRunner
+interface IHostRunner
{
string GetTestCommand();
string GetXharnessArgsWindowsOS(XHarnessArgsOptions options);
new BuildProjectOptions(
InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText),
DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack,
- GlobalizationMode: invariant ? GlobalizationMode.Invariant : fullIcu ? GlobalizationMode.FullIcu : null));
+ GlobalizationMode: invariant ? GlobalizationMode.Invariant : fullIcu ? GlobalizationMode.FullIcu : GlobalizationMode.Default));
string runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id);
}
new BuildProjectOptions(
InitProject: () => File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "InvariantGlobalization.cs"), Path.Combine(_projectDir!, "Program.cs")),
DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack,
- GlobalizationMode: invariantGlobalization == true ? GlobalizationMode.Invariant : null));
+ GlobalizationMode: invariantGlobalization == true ? GlobalizationMode.Invariant : GlobalizationMode.Default));
if (invariantGlobalization == true)
{
using Xunit.Abstractions;
using Xunit.Sdk;
using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
#nullable enable
new BuildProjectOptions(
InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText),
DotnetWasmFromRuntimePack: false,
- GlobalizationMode: invariant ? GlobalizationMode.Invariant : null,
+ GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Default,
CreateProject: true));
RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: RunHost.Chrome, id: id);
File.WriteAllText(Path.Combine(_projectDir!, $"{buildArgs.ProjectName}.csproj"), buildArgs.ProjectFileContents);
buildArgs = newBuildArgs;
+ // artificial delay to have new enough timestamps
+ Thread.Sleep(5000);
+
_testOutput.WriteLine($"{Environment.NewLine}Rebuilding with no changes ..{Environment.NewLine}");
(_, string output) = BuildProject(buildArgs,
id: id,
new BuildProjectOptions(
DotnetWasmFromRuntimePack: false,
- GlobalizationMode: invariant ? GlobalizationMode.Invariant : null,
+ GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Default,
CreateProject: false,
UseCache: false,
Verbosity: verbosity));
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
+using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.RegularExpressions;
+using Microsoft.NET.Sdk.WebAssembly;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Wasm.Build.Tests;
+// For projects using WasmAppBuilder
public abstract class ProjectProviderBase(ITestOutputHelper _testOutput, string? _projectDir)
{
public const string WebcilInWasmExtension = ".wasm";
- protected const string s_dotnetVersionHashRegex = @"\.(?<version>.+)\.(?<hash>[a-zA-Z0-9]+)\.";
+ protected const string s_dotnetVersionHashRegex = @"\.(?<version>[0-9]+\.[0-9]+\.[a-zA-Z0-9\.-]+)\.(?<hash>[a-zA-Z0-9]+)\.";
+
+ private const string s_runtimePackPathPattern = "\\*\\* MicrosoftNetCoreAppRuntimePackDir : '([^ ']*)'";
+ private static Regex s_runtimePackPathRegex = new Regex(s_runtimePackPathPattern);
private static string[] s_dotnetExtensionsToIgnore = new[]
{
".gz",
- ".br",
- ".symbols"
+ ".br"
};
- private const string s_runtimePackPathPattern = "\\*\\* MicrosoftNetCoreAppRuntimePackDir : '([^ ']*)'";
- private static Regex s_runtimePackPathRegex = new Regex(s_runtimePackPathPattern);
public string? ProjectDir { get; set; } = _projectDir;
protected ITestOutputHelper _testOutput = _testOutput;
protected BuildEnvironment _buildEnv = BuildTestBase.s_buildEnv;
+ public string BundleDirName { get; set; } = "wwwroot";
- public IReadOnlyDictionary<string, DotNetFileName> FindAndAssertDotnetFiles(
- string dir,
- bool isPublish,
- bool expectFingerprintOnDotnetJs,
- RuntimeVariant runtimeType)
+ // Returns the actual files on disk
+ public IReadOnlyDictionary<string, DotNetFileName> AssertBasicBundle(AssertBundleOptionsBase assertOptions)
+ {
+ EnsureProjectDirIsSet();
+ var dotnetFiles = FindAndAssertDotnetFiles(assertOptions);
+
+ TestUtils.AssertFilesExist(assertOptions.BinFrameworkDir,
+ new[] { "System.Private.CoreLib.dll" },
+ expectToExist: !BuildTestBase.UseWebcil);
+ TestUtils.AssertFilesExist(assertOptions.BinFrameworkDir,
+ new[] { "System.Private.CoreLib.wasm" },
+ expectToExist: BuildTestBase.UseWebcil);
+
+ AssertBootJson(assertOptions);
+
+ // icu
+ if (assertOptions.AssertIcuAssets)
+ {
+ _testOutput.WriteLine("Skipping asserting icu assets");
+ AssertIcuAssets(assertOptions);
+ }
+
+ // symbols
+ if (assertOptions.AssertSymbolsFile)
+ {
+ _testOutput.WriteLine("Skipping asserting symbols file");
+ AssertDotNetJsSymbols(assertOptions);
+ }
+
+ return dotnetFiles;
+ }
+
+ public IReadOnlyDictionary<string, DotNetFileName> FindAndAssertDotnetFiles(AssertBundleOptionsBase assertOptions)
{
- return FindAndAssertDotnetFiles(dir: dir,
- expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
- superSet: GetAllKnownDotnetFilesToFingerprintMap(runtimeType),
- expected: GetDotNetFilesExpectedSet(runtimeType, isPublish));
+ EnsureProjectDirIsSet();
+ return FindAndAssertDotnetFiles(binFrameworkDir: assertOptions.BinFrameworkDir,
+ expectFingerprintOnDotnetJs: assertOptions.ExpectFingerprintOnDotnetJs,
+ superSet: GetAllKnownDotnetFilesToFingerprintMap(assertOptions),
+ expected: GetDotNetFilesExpectedSet(assertOptions));
}
- protected abstract IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(RuntimeVariant runtimeType);
- protected abstract IReadOnlySet<string> GetDotNetFilesExpectedSet(RuntimeVariant runtimeType, bool isPublish);
+ protected abstract IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(AssertBundleOptionsBase assertOptions);
+ protected abstract IReadOnlySet<string> GetDotNetFilesExpectedSet(AssertBundleOptionsBase assertOptions);
public IReadOnlyDictionary<string, DotNetFileName> FindAndAssertDotnetFiles(
- string dir,
+ string binFrameworkDir,
bool expectFingerprintOnDotnetJs,
IReadOnlyDictionary<string, bool> superSet,
IReadOnlySet<string>? expected)
EnsureProjectDirIsSet();
var actual = new SortedDictionary<string, DotNetFileName>();
- IList<string> dotnetFiles = Directory.EnumerateFiles(dir,
+ if (!Directory.Exists(binFrameworkDir))
+ throw new XunitException($"Could not find bundle directory {binFrameworkDir}");
+
+ IList<string> dotnetFiles = Directory.EnumerateFiles(binFrameworkDir,
"dotnet.*",
SearchOption.TopDirectoryOnly)
.Order()
return false;
string actualFilename = Path.GetFileName(actualFile);
- _testOutput.WriteLine($"Comparing {expectedFilename} with {actualFile}, expectFingerprintOnDotnetJs: {expectFingerprintOnDotnetJs}, expectFingerprint: {expectFingerprint}");
+ // _testOutput.WriteLine($"Comparing {expectedFilename} with {actualFile}, expectFingerprintOnDotnetJs: {expectFingerprintOnDotnetJs}, expectFingerprint: {expectFingerprint}");
if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
expectFingerprintForThisFile: expectFingerprint))
}).ToList();
}
- _testOutput.WriteLine($"Accepted count: {actual.Count}");
- foreach (var kvp in actual)
- _testOutput.WriteLine($"Accepted: \t[{kvp.Key}] = {kvp.Value}");
+ // _testOutput.WriteLine($"Accepted count: {actual.Count}");
+ // foreach (var kvp in actual)
+ // _testOutput.WriteLine($"Accepted: \t[{kvp.Key}] = {kvp.Value}");
if (dotnetFiles.Any())
{
- throw new XunitException($"Found unknown files in {dir}:{Environment.NewLine} {string.Join($"{Environment.NewLine} ", dotnetFiles)}");
+ 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");
}
if (expected is not null)
- AssertDotNetFilesSet(expected, superSet, actual, expectFingerprintOnDotnetJs);
+ AssertDotNetFilesSet(expected, superSet, actual, expectFingerprintOnDotnetJs, binFrameworkDir);
return actual;
}
- public void AssertDotNetFilesSet(
+ private void AssertDotNetFilesSet(
IReadOnlySet<string> expected,
IReadOnlyDictionary<string, bool> superSet,
- IDictionary<string, DotNetFileName> actual,
- bool expectFingerprintOnDotnetJs)
+ IReadOnlyDictionary<string, DotNetFileName> actualReadOnly,
+ bool expectFingerprintOnDotnetJs,
+ string bundleDir)
{
EnsureProjectDirIsSet();
+
+ var actual = new Dictionary<string, DotNetFileName>(actualReadOnly);
foreach (string expectedFilename in expected)
{
bool expectFingerprint = superSet[expectedFilename];
- Assert.True(actual.ContainsKey(expectedFilename), $"Could not find {expectedFilename} in {string.Join(", ", actual.Keys)}");
+ Assert.True(actual.ContainsKey(expectedFilename), $"Could not find {expectedFilename} in the list of actual files on disk - {string.Join(", ", actual.Keys)} in bundle directory: {bundleDir}");
// Check that the version and hash are present or not present as expected
if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
if (!string.IsNullOrEmpty(actual[expectedFilename].Hash))
throw new XunitException($"Expected no hash in filename: {actual[expectedFilename].ActualPath}");
}
+ actual.Remove(expectedFilename);
}
- if (expected.Count < actual.Count)
+ if (actual.Any())
{
- StringBuilder sb = new();
- sb.AppendLine($"Expected: {string.Join(", ", expected)}");
- // FIXME: show the difference in a better way
- sb.AppendLine($"Actual: {string.Join(", ", actual.Values.Select(a => a.ActualPath).Order())}");
- throw new XunitException($"Expected and actual file sets do not match.{Environment.NewLine}{sb}");
+ var actualFileNames = actual.Values.Select(x => x.ActualPath).Order();
+ throw new XunitException($"Found unexpected files: {string.Join(", ", actualFileNames)}");
}
}
return table;
}
+ public static string FindSubDirIgnoringCase(string parentDir, string dirName)
+ {
+ IEnumerable<string> matchingDirs = Directory.EnumerateDirectories(parentDir,
+ dirName,
+ new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive });
+
+ string? first = matchingDirs.FirstOrDefault();
+ if (matchingDirs.Count() > 1)
+ throw new Exception($"Found multiple directories with names that differ only in case. {string.Join(", ", matchingDirs.ToArray())}");
+
+ return first ?? Path.Combine(parentDir, dirName);
+ }
+
public IDictionary<string, (string fullPath, bool unchanged)> GetFilesTable(bool unchanged, params string[] baseDirs)
{
var dict = new Dictionary<string, (string fullPath, bool unchanged)>();
return dict;
}
- public static string FindSubDirIgnoringCase(string parentDir, string dirName)
- {
- IEnumerable<string> matchingDirs = Directory.EnumerateDirectories(parentDir,
- dirName,
- new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive });
-
- string? first = matchingDirs.FirstOrDefault();
- if (matchingDirs.Count() > 1)
- throw new Exception($"Found multiple directories with names that differ only in case. {string.Join(", ", matchingDirs.ToArray())}");
-
- return first ?? Path.Combine(parentDir, dirName);
- }
public static bool ShouldCheckFingerprint(string expectedFilename, bool expectFingerprintOnDotnetJs, bool expectFingerprintForThisFile) =>
(expectedFilename == "dotnet.js" && expectFingerprintOnDotnetJs) || expectFingerprintForThisFile;
+
public static void AssertRuntimePackPath(string buildOutput, string targetFramework)
{
var match = s_runtimePackPathRegex.Match(buildOutput);
throw new XunitException($"Runtime pack path doesn't match.{Environment.NewLine}Expected: '{expectedRuntimePackDir}'{Environment.NewLine}Actual: '{actualPath}'");
}
- public static void AssertDotNetJsSymbols(string bundleDir, bool fromRuntimePack, string targetFramework)
- => TestUtils.AssertFile(Path.Combine(BuildTestBase.s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.js.symbols"),
- Path.Combine(bundleDir, "_framework/dotnet.native.js.symbols"),
- same: fromRuntimePack);
+ public static void AssertDotNetJsSymbols(AssertBundleOptionsBase assertOptions)
+ {
+ TestUtils.AssertFilesExist(assertOptions.BinFrameworkDir, new[] { "dotnet.native.js.symbols" }, expectToExist: assertOptions.ExpectSymbolsFile);
+
+ if (assertOptions.ExpectedFileType == NativeFilesType.FromRuntimePack)
+ {
+ TestUtils.AssertFile(
+ Path.Combine(BuildTestBase.s_buildEnv.GetRuntimeNativeDir(assertOptions.TargetFramework, assertOptions.RuntimeType), "dotnet.native.js.symbols"),
+ Path.Combine(assertOptions.BinFrameworkDir, "dotnet.native.js.symbols"),
+ same: true);
+ }
+ }
+
+ public void AssertIcuAssets(AssertBundleOptionsBase assertOptions)
+ {
+ List<string> expected = new();
+ switch (assertOptions.GlobalizationMode)
+ {
+ case GlobalizationMode.Invariant:
+ break;
+ case GlobalizationMode.FullIcu:
+ expected.Add("icudt.dat");
+ break;
+ case GlobalizationMode.Hybrid:
+ expected.Add("icudt_hybrid.dat");
+ break;
+ case GlobalizationMode.PredefinedIcu:
+ if (string.IsNullOrEmpty(assertOptions.PredefinedIcudt))
+ throw new ArgumentException("WasmBuildTest is invalid, value for predefinedIcudt is required when GlobalizationMode=PredefinedIcu.");
+
+ // predefined ICU name can be identical with the icu files from runtime pack
+ expected.Add(assertOptions.PredefinedIcudt);
+ break;
+ case GlobalizationMode.Default:
+ // icu shard chosen based on the locale
+ expected.Add("icudt_CJK.dat");
+ expected.Add("icudt_EFIGS.dat");
+ expected.Add("icudt_no_CJK.dat");
+ break;
+ default:
+ throw new NotImplementedException($"Unknown {nameof(assertOptions.GlobalizationMode)} = {assertOptions.GlobalizationMode}");
+ }
+
+ IEnumerable<string> actual = Directory.EnumerateFiles(assertOptions.BinFrameworkDir, "icudt*dat");
+ AssertFilesOnDisk(expected, actual);
+ if (assertOptions.GlobalizationMode is GlobalizationMode.PredefinedIcu)
+ TestUtils.AssertSameFile(assertOptions.PredefinedIcudt!, actual.Single());
+ }
+
+ public void AssertBootJson(AssertBundleOptionsBase options)
+ {
+ EnsureProjectDirIsSet();
+ // string binFrameworkDir = FindBinFrameworkDir(options.Config, options.IsPublish, options.TargetFramework);
+ string binFrameworkDir = options.BinFrameworkDir;
+ string bootJsonPath = Path.Combine(binFrameworkDir, options.BootJsonFileName);
+ Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");
+
+ BootJsonData bootJson = ParseBootData(bootJsonPath);
+ var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();
+
+ var expectedEntries = new SortedDictionary<string, Action<string>>();
+ IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(options);
+
+ var knownSet = GetAllKnownDotnetFilesToFingerprintMap(options);
+ foreach (string expectedFilename in expected)
+ {
+ if (Path.GetExtension(expectedFilename) == ".map")
+ continue;
+
+ bool expectFingerprint = knownSet[expectedFilename];
+ expectedEntries[expectedFilename] = item =>
+ {
+ string prefix = Path.GetFileNameWithoutExtension(expectedFilename);
+ string extension = Path.GetExtension(expectedFilename).Substring(1);
+
+ if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
+ expectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs,
+ expectFingerprintForThisFile: expectFingerprint))
+ {
+ Assert.Matches($"{prefix}{s_dotnetVersionHashRegex}{extension}", item);
+ }
+ else
+ {
+ Assert.Equal(expectedFilename, item);
+ }
+
+ string absolutePath = Path.Combine(binFrameworkDir, item);
+ Assert.True(File.Exists(absolutePath), $"Expected to find '{absolutePath}'");
+ };
+ }
+ // FIXME: maybe use custom code so the details can show up in the log
+ bootJsonEntries = bootJsonEntries.Order().ToArray();
+ if (bootJsonEntries.Length != expectedEntries.Count)
+ {
+ throw new XunitException($"In {bootJsonPath}{Environment.NewLine}" +
+ $" Expected: {string.Join(", ", expectedEntries.Keys.ToArray())}{Environment.NewLine}" +
+ $" Actual : {string.Join(", ", bootJsonEntries)}");
+
+
+ }
+ Assert.Collection(bootJsonEntries.Order(), expectedEntries.Values.ToArray());
+ }
+
+ public static BootJsonData ParseBootData(string bootJsonPath)
+ {
+ using FileStream stream = File.OpenRead(bootJsonPath);
+ stream.Position = 0;
+ var serializer = new DataContractJsonSerializer(
+ typeof(BootJsonData),
+ new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });
+
+ var config = (BootJsonData?)serializer.ReadObject(stream);
+ Assert.NotNull(config);
+ return config;
+ }
+
+ private void AssertFilesOnDisk(IEnumerable<string> expected, IEnumerable<string> actual)
+ {
+ expected = expected.Order().Select(f => Path.GetFileName(f)).Distinct();
+ var actualFileNames = actual.Order().Select(f => Path.GetFileName(f));
+ Assert.True(expected.Count() == actualFileNames.Count(),
+ $"Expected: {string.Join(", ", expected)}{Environment.NewLine}" +
+ $"Actual: {string.Join(", ", actualFileNames)}");
+
+ Assert.Equal(expected, actualFileNames);
+ }
+
+ public virtual string FindBinFrameworkDir(string config, bool forPublish, string framework, string? bundleDirName = null)
+ {
+ EnsureProjectDirIsSet();
+ string basePath = Path.Combine(ProjectDir!, "bin", config, framework);
+ if (forPublish)
+ basePath = FindSubDirIgnoringCase(basePath, "publish");
+
+ return Path.Combine(basePath, bundleDirName ?? this.BundleDirName, "_framework");
+ }
[MemberNotNull(nameof(ProjectDir))]
protected void EnsureProjectDirIsSet()
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
[Theory]
[MemberData(nameof(NonNativeDebugRebuildData))]
- public void NoOpRebuild(BuildArgs buildArgs, RunHost host, string id)
+ public async Task NoOpRebuild(BuildArgs buildArgs, RunHost host, string id)
{
string projectName = $"rebuild_{buildArgs.Config}_{buildArgs.AOT}";
File.Move(product!.LogFile, Path.ChangeExtension(product.LogFile!, ".first.binlog"));
+ // artificial delay to have new enough timestamps
+ await Task.Delay(5000);
+
_testOutput.WriteLine($"{Environment.NewLine}Rebuilding with no changes ..{Environment.NewLine}");
// no-op Rebuild
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
TargetFramework: BuildTestBase.DefaultTargetFramework
));
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: true, targetFramework: DefaultTargetFramework);
-
if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product))
throw new XunitException($"Test bug: could not get the build product in the cache");
Publish: true,
TargetFramework: BuildTestBase.DefaultTargetFramework,
UseCache: false));
-
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !expectRelinking, targetFramework: DefaultTargetFramework);
}
[Theory]
IsBrowserProject: false
));
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: true, targetFramework: DefaultTargetFramework);
-
CommandResult res = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!)
.ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config}")
TargetFramework: BuildTestBase.DefaultTargetFramework,
UseCache: false,
IsBrowserProject: false));
-
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !expectRelinking, targetFramework: DefaultTargetFramework);
}
[ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))]
IsBrowserProject: false
));
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config, expectedTFM), "AppBundle"), fromRuntimePack: !relinking, targetFramework: expectedTFM);
-
CommandResult res = new RunCommand(s_buildEnv, _testOutput)
.WithWorkingDirectory(_projectDir!)
.ExecuteWithCapturedOutput($"run --no-silent --no-build -c {config} x y z")
UseCache: false,
IsBrowserProject: false));
- if (!aot)
- {
- // These are disabled for AOT explicitly
- ProjectProviderBase.AssertDotNetJsSymbols(Path.Combine(GetBinDir(config), "AppBundle"), fromRuntimePack: !expectRelinking, targetFramework: DefaultTargetFramework);
- }
- else
- {
- TestUtils.AssertFilesDontExist(Path.Combine(GetBinDir(config), "AppBundle"), new[] { "dotnet.native.js.symbols" });
- }
-
string runArgs = $"run --no-silent --no-build -c {config}";
runArgs += " x y z";
var res = new RunCommand(s_buildEnv, _testOutput, label: id)
{
public TestMainJsProjectProvider(ITestOutputHelper _testOutput, string? _projectDir = null)
: base(_testOutput, _projectDir)
- {}
+ {
+ BundleDirName = "AppBundle";
+ }
// no fingerprinting
- protected override IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(RuntimeVariant runtimeType)
+ protected override IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(AssertBundleOptionsBase assertOptions)
=> new SortedDictionary<string, bool>()
{
{ "dotnet.js", false },
{ "dotnet.js.map", false },
{ "dotnet.native.js", false },
+ { "dotnet.native.js.symbols", false },
{ "dotnet.native.wasm", false },
{ "dotnet.native.worker.js", false },
{ "dotnet.runtime.js", false },
{ "dotnet.runtime.js.map", false }
};
- protected override IReadOnlySet<string> GetDotNetFilesExpectedSet(RuntimeVariant runtimeType, bool isPublish)
+ protected override IReadOnlySet<string> GetDotNetFilesExpectedSet(AssertBundleOptionsBase assertOptions)
{
- SortedSet<string>? res = null;
- if (runtimeType is RuntimeVariant.SingleThreaded)
+ SortedSet<string>? res = new();
+ if (assertOptions.RuntimeType is RuntimeVariant.SingleThreaded)
{
- res = new SortedSet<string>()
- {
- "dotnet.js",
- "dotnet.native.wasm",
- "dotnet.native.js",
- "dotnet.runtime.js",
- };
-
+ res.Add("dotnet.js");
+ res.Add("dotnet.native.wasm");
+ res.Add("dotnet.native.js");
+ res.Add("dotnet.runtime.js");
res.Add("dotnet.js.map");
res.Add("dotnet.runtime.js.map");
}
- if (runtimeType is RuntimeVariant.MultiThreaded)
+ if (assertOptions.RuntimeType is RuntimeVariant.MultiThreaded)
{
- res = new SortedSet<string>()
- {
- "dotnet.js",
- "dotnet.native.js",
- "dotnet.native.wasm",
- "dotnet.native.worker.js",
- "dotnet.runtime.js",
- };
- if (!isPublish)
+ res.Add("dotnet.js");
+ res.Add("dotnet.native.wasm");
+ res.Add("dotnet.native.js");
+ res.Add("dotnet.runtime.js");
+ res.Add("dotnet.native.worker.js");
+
+ if (!assertOptions.IsPublish)
{
res.Add("dotnet.js.map");
res.Add("dotnet.runtime.js.map");
}
}
- return res ?? throw new ArgumentException($"Unknown runtime type: {runtimeType}");
+ if (assertOptions.AssertSymbolsFile && assertOptions.ExpectSymbolsFile)
+ res.Add("dotnet.native.js.symbols");
+
+ return res ?? throw new ArgumentException($"Unknown runtime type: {assertOptions.RuntimeType}");
}
- public void AssertBasicAppBundle(AssertTestMainJsAppBundleOptions options)
+ public void AssertBundle(AssertTestMainJsAppBundleOptions assertOptions)
{
- EnsureProjectDirIsSet();
- new TestMainJsProjectProvider(_testOutput, ProjectDir)
- .FindAndAssertDotnetFiles(
- Path.Combine(options.BundleDir, "_framework"),
- isPublish: options.IsPublish,
- expectFingerprintOnDotnetJs: false,
- runtimeType: RuntimeVariant.SingleThreaded);
-
- var filesToExist = new List<string>()
- {
- options.MainJS,
- "_framework/blazor.boot.json",
- "_framework/dotnet.js.map",
- "_framework/dotnet.runtime.js.map",
- };
-
- if (options.IsBrowserProject)
- filesToExist.Add("index.html");
-
- TestUtils.AssertFilesExist(options.BundleDir, filesToExist);
+ AssertBasicBundle(assertOptions);
- TestUtils.AssertFilesExist(options.BundleDir, new[] { "run-v8.sh" }, expectToExist: options.HasV8Script);
- AssertIcuAssets();
+ TestUtils.AssertFilesExist(assertOptions.BundleDir, new[] { assertOptions.MainJS });
+ if (assertOptions.IsBrowserProject)
+ TestUtils.AssertFilesExist(assertOptions.BundleDir, new[] { "index.html" });
+ TestUtils.AssertFilesExist(assertOptions.BundleDir, new[] { "run-v8.sh" }, expectToExist: assertOptions.HasV8Script);
- string managedDir = Path.Combine(options.BundleDir, "_framework");
string bundledMainAppAssembly =
- options.UseWebcil ? $"{options.ProjectName}{WebcilInWasmExtension}" : $"{options.ProjectName}.dll";
- TestUtils.AssertFilesExist(managedDir, new[] { bundledMainAppAssembly });
-
- bool is_debug = options.Config == "Debug";
- if (is_debug)
- {
- // Use cecil to check embedded pdb?
- // AssertFilesExist(managedDir, new[] { $"{projectName}.pdb" });
-
- //FIXME: um.. what about these? embedded? why is linker omitting them?
- //foreach (string file in Directory.EnumerateFiles(managedDir, "*.dll"))
- //{
- //string pdb = Path.ChangeExtension(file, ".pdb");
- //Assert.True(File.Exists(pdb), $"Could not find {pdb} for {file}");
- //}
- }
+ BuildTestBase.UseWebcil ? $"{assertOptions.ProjectName}{WebcilInWasmExtension}" : $"{assertOptions.ProjectName}.dll";
+ TestUtils.AssertFilesExist(assertOptions.BinFrameworkDir, new[] { bundledMainAppAssembly });
+ }
- void AssertIcuAssets()
- {
- bool expectEFIGS = false;
- bool expectCJK = false;
- bool expectNOCJK = false;
- bool expectFULL = false;
- bool expectHYBRID = false;
- switch (options.GlobalizationMode)
- {
- case GlobalizationMode.Invariant:
- break;
- case GlobalizationMode.FullIcu:
- expectFULL = true;
- break;
- case GlobalizationMode.Hybrid:
- expectHYBRID = true;
- break;
- case GlobalizationMode.PredefinedIcu:
- if (string.IsNullOrEmpty(options.PredefinedIcudt))
- throw new ArgumentException("WasmBuildTest is invalid, value for predefinedIcudt is required when GlobalizationMode=PredefinedIcu.");
- TestUtils.AssertFilesExist(options.BundleDir, new[] { Path.Combine("_framework", options.PredefinedIcudt) }, expectToExist: true);
- // predefined ICU name can be identical with the icu files from runtime pack
- switch (options.PredefinedIcudt)
- {
- case "icudt.dat":
- expectFULL = true;
- break;
- case "icudt_EFIGS.dat":
- expectEFIGS = true;
- break;
- case "icudt_CJK.dat":
- expectCJK = true;
- break;
- case "icudt_no_CJK.dat":
- expectNOCJK = true;
- break;
- }
- break;
- default:
- // icu shard chosen based on the locale
- expectCJK = true;
- expectEFIGS = true;
- expectNOCJK = true;
- break;
- }
+ public void AssertBundle(BuildArgs buildArgs, BuildProjectOptions buildProjectOptions)
+ {
+ string binFrameworkDir = FindBinFrameworkDir(buildArgs.Config,
+ buildProjectOptions.Publish,
+ buildProjectOptions.TargetFramework);
+ NativeFilesType expectedFileType = buildArgs.AOT
+ ? NativeFilesType.AOT
+ : buildProjectOptions.DotnetWasmFromRuntimePack == false
+ ? NativeFilesType.Relinked
+ : NativeFilesType.FromRuntimePack;
+
+ var assertOptions = new AssertTestMainJsAppBundleOptions(
+ Config: buildArgs.Config,
+ IsPublish: buildProjectOptions.Publish,
+ TargetFramework: buildProjectOptions.TargetFramework!,
+ BinFrameworkDir: binFrameworkDir,
+ ProjectName: buildArgs.ProjectName,
+ MainJS: buildProjectOptions.MainJS ?? "test-main.js",
+ GlobalizationMode: buildProjectOptions.GlobalizationMode,
+ HasV8Script: buildProjectOptions.HasV8Script,
+ PredefinedIcudt: buildProjectOptions.PredefinedIcudt ?? string.Empty,
+ IsBrowserProject: buildProjectOptions.IsBrowserProject,
+ ExpectedFileType: expectedFileType,
+ ExpectSymbolsFile: !buildArgs.AOT);
+ AssertBundle(assertOptions);
+ }
- var frameworkDir = Path.Combine(options.BundleDir, "_framework");
- TestUtils.AssertFilesExist(frameworkDir, new[] { "icudt.dat" }, expectToExist: expectFULL);
- TestUtils.AssertFilesExist(frameworkDir, new[] { "icudt_EFIGS.dat" }, expectToExist: expectEFIGS);
- TestUtils.AssertFilesExist(frameworkDir, new[] { "icudt_CJK.dat" }, expectToExist: expectCJK);
- TestUtils.AssertFilesExist(frameworkDir, new[] { "icudt_no_CJK.dat" }, expectToExist: expectNOCJK);
- TestUtils.AssertFilesExist(frameworkDir, new[] { "icudt_hybrid.dat" }, expectToExist: expectHYBRID);
- }
+ public override string FindBinFrameworkDir(string config, bool forPublish, string framework, string? bundleDirName = null)
+ {
+ EnsureProjectDirIsSet();
+ return Path.Combine(ProjectDir!, "bin", config, framework, "browser-wasm", bundleDirName ?? this.BundleDirName, "_framework");
}
}
#nullable enable
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Text;
using Xunit.Abstractions;
using Xunit.Sdk;
throw new Exception("_projectDir should be set, to use options.createProject=false");
}
- StringBuilder sb = new();
- sb.Append(options.Publish ? "publish" : "build");
- if (options.Publish && options.BuildOnlyAfterPublish)
- sb.Append(" -p:WasmBuildOnlyAfterPublish=true");
- sb.Append($" {s_buildEnv.DefaultBuildArgs}");
-
- sb.Append($" /p:Configuration={buildArgs.Config}");
-
- string logFileSuffix = options.Label == null ? string.Empty : options.Label.Replace(' ', '_');
- string logFilePath = Path.Combine(_logPath, $"{buildArgs.ProjectName}{logFileSuffix}.binlog");
- _testOutput.WriteLine($"-------- Building ---------");
- _testOutput.WriteLine($"Binlog path: {logFilePath}");
- sb.Append($" /bl:\"{logFilePath}\" /nologo");
- sb.Append($" /v:{options.Verbosity ?? "minimal"}");
- if (buildArgs.ExtraBuildArgs != null)
- sb.Append($" {buildArgs.ExtraBuildArgs} ");
-
- _testOutput.WriteLine($"Building {buildArgs.ProjectName} in {_projectDir}");
-
- (int exitCode, string buildOutput) result;
try
{
- var envVars = s_buildEnv.EnvVars;
- if (options.ExtraBuildEnvironmentVariables is not null)
- {
- envVars = new Dictionary<string, string>(s_buildEnv.EnvVars);
- foreach (var kvp in options.ExtraBuildEnvironmentVariables!)
- envVars[kvp.Key] = kvp.Value;
- }
- envVars["NUGET_PACKAGES"] = _nugetPackagesDir;
- result = AssertBuild(sb.ToString(), id, expectSuccess: options.ExpectSuccess, envVars: envVars);
-
- // check that we are using the correct runtime pack!
+ (CommandResult res, string logFilePath) = BuildProjectWithoutAssert(id,
+ buildArgs.Config,
+ options,
+ string.Join(" ", buildArgs.ExtraBuildArgs));
if (options.ExpectSuccess && options.AssertAppBundle)
{
- ProjectProviderBase.AssertRuntimePackPath(result.buildOutput, options.TargetFramework ?? DefaultTargetFramework);
-
- string bundleDir = Path.Combine(GetBinDir(config: buildArgs.Config, targetFramework: options.TargetFramework ?? DefaultTargetFramework), "AppBundle");
- _provider.AssertBasicAppBundle(new AssertTestMainJsAppBundleOptions(
- BundleDir: bundleDir,
- ProjectName: buildArgs.ProjectName,
- Config: buildArgs.Config,
- MainJS: options.MainJS ?? "test-main.js",
- HasV8Script: options.HasV8Script,
- GlobalizationMode: options.GlobalizationMode,
- PredefinedIcudt: options.PredefinedIcudt ?? "",
- UseWebcil: UseWebcil,
- IsBrowserProject: options.IsBrowserProject,
- IsPublish: options.Publish));
+ ProjectProviderBase.AssertRuntimePackPath(res.Output, options.TargetFramework ?? DefaultTargetFramework);
+ _provider.AssertBundle(buildArgs, options);
}
if (options.UseCache)
- _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, logFilePath, true, result.buildOutput));
+ _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, logFilePath, true, res.Output));
- return (_projectDir, result.buildOutput);
+ return (_projectDir, res.Output);
}
catch (Exception ex)
{
if (options.UseCache)
- _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, logFilePath, false, $"The build attempt resulted in exception: {ex}."));
+ _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, /*logFilePath*/"unset-log-path", false, $"The build attempt resulted in exception: {ex}."));
throw;
}
}
-
- protected (int exitCode, string buildOutput) AssertBuild(string args, string label = "build", bool expectSuccess = true, IDictionary<string, string>? envVars = null, int? timeoutMs = null)
- {
- var result = RunProcess(s_buildEnv.DotNet, _testOutput, args, workingDir: _projectDir, label: label, envVars: envVars, timeoutMs: timeoutMs ?? s_defaultPerTestTimeoutMs);
- if (expectSuccess && result.exitCode != 0)
- throw new XunitException($"Build process exited with non-zero exit code: {result.exitCode}");
- if (!expectSuccess && result.exitCode == 0)
- throw new XunitException($"Build should have failed, but it didn't. Process exited with exitCode : {result.exitCode}");
-
- return result;
- }
}
// 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.Runtime.Serialization.Json;
-using Microsoft.NET.Sdk.WebAssembly;
-using Xunit;
+using System.Collections.Generic;
using Xunit.Abstractions;
+using Xunit.Sdk;
+using System.Linq;
#nullable enable
: base(_testOutput, _projectDir)
{}
- protected override IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(RuntimeVariant runtimeType)
+ protected override IReadOnlyDictionary<string, bool> GetAllKnownDotnetFilesToFingerprintMap(AssertBundleOptionsBase assertOptions)
=> new SortedDictionary<string, bool>()
{
{ "dotnet.js", false },
{ "dotnet.js.map", false },
{ "dotnet.native.js", true },
+ { "dotnet.native.js.symbols", false },
{ "dotnet.native.wasm", false },
{ "dotnet.native.worker.js", true },
{ "dotnet.runtime.js", true },
- { "dotnet.runtime.js.map", false }
+ { "dotnet.runtime.js.map", false },
};
- protected override IReadOnlySet<string> GetDotNetFilesExpectedSet(RuntimeVariant runtimeType, bool isPublish)
+ protected override IReadOnlySet<string> GetDotNetFilesExpectedSet(AssertBundleOptionsBase assertOptions)
{
SortedSet<string> res = new()
{
"dotnet.native.js",
"dotnet.runtime.js",
};
- if (runtimeType is RuntimeVariant.MultiThreaded)
+ if (assertOptions.RuntimeType is RuntimeVariant.MultiThreaded)
{
res.Add("dotnet.native.worker.js");
}
- if (!isPublish)
+ if (!assertOptions.IsPublish)
{
res.Add("dotnet.js.map");
res.Add("dotnet.runtime.js.map");
}
+ if (assertOptions.AssertSymbolsFile && assertOptions.ExpectSymbolsFile)
+ res.Add("dotnet.native.js.symbols");
+
return res;
}
- public void AssertDotNetNativeFiles(
- NativeFilesType type,
- string config,
- bool forPublish,
- string targetFramework,
- bool expectFingerprintOnDotnetJs,
- RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded)
+ public void AssertBundle(AssertWasmSdkBundleOptions assertOptions)
{
- EnsureProjectDirIsSet();
- string label = forPublish ? "publish" : "build";
- string objBuildDir = Path.Combine(ProjectDir, "obj", config, targetFramework, "wasm", forPublish ? "for-publish" : "for-build");
- string binFrameworkDir = FindBlazorBinFrameworkDir(config, forPublish, framework: targetFramework);
+ IReadOnlyDictionary<string, DotNetFileName> actualDotnetFiles = AssertBasicBundle(assertOptions);
+
+ if (!BuildTestBase.IsUsingWorkloads)
+ return;
- var dotnetFiles = FindAndAssertDotnetFiles(
- dir: binFrameworkDir,
- isPublish: forPublish,
- expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
- runtimeType: runtimeType);
+ // Compare files with the runtime pack
+ string objBuildDir = Path.Combine(ProjectDir!, "obj", assertOptions.Config, assertOptions.TargetFramework, "wasm", assertOptions.IsPublish ? "for-publish" : "for-build");
- string runtimeNativeDir = _buildEnv.GetRuntimeNativeDir(targetFramework, runtimeType);
+ string runtimeNativeDir = BuildTestBase.s_buildEnv.GetRuntimeNativeDir(assertOptions.TargetFramework, assertOptions.RuntimeType);
- string srcDirForNativeFileToCompareAgainst = type switch
+ string srcDirForNativeFileToCompareAgainst = assertOptions.ExpectedFileType switch
{
NativeFilesType.FromRuntimePack => runtimeNativeDir,
NativeFilesType.Relinked => objBuildDir,
NativeFilesType.AOT => objBuildDir,
- _ => throw new ArgumentOutOfRangeException(nameof(type))
+ _ => throw new ArgumentOutOfRangeException(nameof(assertOptions.ExpectedFileType))
};
+ string buildType = assertOptions.IsPublish ? "publish" : "build";
foreach (string nativeFilename in new[] { "dotnet.native.wasm", "dotnet.native.js" })
{
+ if (!actualDotnetFiles.TryGetValue(nativeFilename, out DotNetFileName? dotnetFile))
+ {
+ throw new XunitException($"Could not find {nativeFilename}. Actual files on disk: {string.Join($"{Environment.NewLine} ", actualDotnetFiles.Values.Select(a => a.ActualPath).Order())}");
+
+ }
// For any *type*, check against the expected path
TestUtils.AssertSameFile(Path.Combine(srcDirForNativeFileToCompareAgainst, nativeFilename),
- dotnetFiles[nativeFilename].ActualPath,
- label);
+ actualDotnetFiles[nativeFilename].ActualPath,
+ buildType);
- if (type != NativeFilesType.FromRuntimePack)
+ if (assertOptions.ExpectedFileType != NativeFilesType.FromRuntimePack)
{
// Confirm that it doesn't match the file from the runtime pack
TestUtils.AssertNotSameFile(Path.Combine(runtimeNativeDir, nativeFilename),
- dotnetFiles[nativeFilename].ActualPath,
- label);
+ actualDotnetFiles[nativeFilename].ActualPath,
+ buildType);
}
}
}
- public void AssertBootJson(
- string binFrameworkDir,
- bool expectFingerprintOnDotnetJs = false,
- bool isPublish = false,
- RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded)
- {
- EnsureProjectDirIsSet();
- string bootJsonPath = Path.Combine(binFrameworkDir, "blazor.boot.json");
- Assert.True(File.Exists(bootJsonPath), $"Expected to find {bootJsonPath}");
-
- BootJsonData bootJson = ParseBootData(bootJsonPath);
- var bootJsonEntries = bootJson.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.", StringComparison.Ordinal)).ToArray();
-
- var expectedEntries = new SortedDictionary<string, Action<string>>();
- IReadOnlySet<string> expected = GetDotNetFilesExpectedSet(runtimeType, isPublish);
-
- var knownSet = GetAllKnownDotnetFilesToFingerprintMap(runtimeType);
- foreach (string expectedFilename in expected)
- {
- if (Path.GetExtension(expectedFilename) == ".map")
- continue;
-
- bool expectFingerprint = knownSet[expectedFilename];
- expectedEntries[expectedFilename] = item =>
- {
- string prefix = Path.GetFileNameWithoutExtension(expectedFilename);
- string extension = Path.GetExtension(expectedFilename).Substring(1);
-
- if (ShouldCheckFingerprint(expectedFilename: expectedFilename,
- expectFingerprintOnDotnetJs: expectFingerprintOnDotnetJs,
- expectFingerprintForThisFile: expectFingerprint))
- {
- Assert.Matches($"{prefix}{s_dotnetVersionHashRegex}{extension}", item);
- }
- else
- {
- Assert.Equal(expectedFilename, item);
- }
-
- string absolutePath = Path.Combine(binFrameworkDir, item);
- Assert.True(File.Exists(absolutePath), $"Expected to find '{absolutePath}'");
- };
- }
- // FIXME: maybe use custom code so the details can show up in the log
- Assert.Collection(bootJsonEntries.Order(), expectedEntries.Values.ToArray());
- }
-
- public static BootJsonData ParseBootData(string bootJsonPath)
- {
- using FileStream stream = File.OpenRead(bootJsonPath);
- stream.Position = 0;
- var serializer = new DataContractJsonSerializer(
- typeof(BootJsonData),
- new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });
-
- var config = (BootJsonData?)serializer.ReadObject(stream);
- Assert.NotNull(config);
- return config;
- }
-
- public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework)
- {
- EnsureProjectDirIsSet();
- string basePath = Path.Combine(ProjectDir, "bin", config, framework);
- if (forPublish)
- basePath = FindSubDirIgnoringCase(basePath, "publish");
-
- return Path.Combine(basePath, "wwwroot", "_framework");
- }
}
// 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;
+#nullable enable
+
using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-using Xunit;
using Xunit.Abstractions;
-using Xunit.Sdk;
-
-#nullable enable
namespace Wasm.Build.Tests;
-public class WasmTemplateTestBase : BuildTestBase
+public abstract class WasmTemplateTestBase : BuildTestBase
{
private readonly WasmSdkBasedProjectProvider _provider;
protected WasmTemplateTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext, WasmSdkBasedProjectProvider? projectProvider = null)
: base(projectProvider ?? new WasmSdkBasedProjectProvider(output), output, buildContext)
{
_provider = GetProvider<WasmSdkBasedProjectProvider>();
+ // Wasm templates are not using wasm sdk yet
+ _provider.BundleDirName = "AppBundle";
}
public string CreateWasmTemplateProject(string id, string template = "wasmbrowser", string extraArgs = "", bool runAnalyzers = true)
{
InitPaths(id);
+ _testOutput.WriteLine($"after initpaths: {_provider.ProjectDir}");
InitProjectDir(_projectDir, addNuGetSourceForLocalPackages: true);
File.WriteAllText(Path.Combine(_projectDir, "Directory.Build.props"), "<Project />");
extraProperties += "<TreatWarningsAsErrors>true</TreatWarningsAsErrors>";
if (runAnalyzers)
extraProperties += "<RunAnalyzers>true</RunAnalyzers>";
- if (!UseWebcil)
- extraProperties += "<WasmEnableWebcil>false</WasmEnableWebcil>";
// TODO: Can be removed after updated templates propagate in.
string extraItems = string.Empty;
}
public (string projectDir, string buildOutput) BuildTemplateProject(BuildArgs buildArgs,
- string id,
- BuildProjectOptions buildProjectOptions,
- AssertTestMainJsAppBundleOptions? assertAppBundleOptions = null)
+ string id,
+ BuildProjectOptions buildProjectOptions,
+ AssertTestMainJsAppBundleOptions? assertAppBundleOptions = null)
{
- StringBuilder buildCmdLine = new();
- buildCmdLine.Append(buildProjectOptions.Publish ? "publish" : "build");
-
- string logFilePath = Path.Combine(s_buildEnv.LogRootPath, $"{id}.binlog");
- _testOutput.WriteLine($"-------- Building ---------");
- _testOutput.WriteLine($"Binlog path: {logFilePath}");
- buildCmdLine.Append($" -c {buildArgs.Config} -bl:{logFilePath} {buildArgs.ExtraBuildArgs}");
-
- if (buildProjectOptions.Publish && buildProjectOptions.BuildOnlyAfterPublish)
- buildCmdLine.Append(" -p:WasmBuildOnlyAfterPublish=true");
-
- CommandResult res = new DotNetCommand(s_buildEnv, _testOutput)
- .WithWorkingDirectory(_projectDir!)
- .WithEnvironmentVariables(buildProjectOptions.ExtraBuildEnvironmentVariables)
- .ExecuteWithCapturedOutput(buildCmdLine.ToString());
- if (buildProjectOptions.ExpectSuccess)
- res.EnsureSuccessful();
- else
- Assert.NotEqual(0, res.ExitCode);
-
+ (CommandResult res, string logFilePath) = BuildProjectWithoutAssert(id, buildArgs.Config, buildProjectOptions);
if (buildProjectOptions.UseCache)
_buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir!, logFilePath, true, res.Output));
- ProjectProviderBase.AssertRuntimePackPath(res.Output, buildProjectOptions.TargetFramework ?? DefaultTargetFramework);
- string bundleDir = Path.Combine(GetBinDir(config: buildArgs.Config, targetFramework: buildProjectOptions.TargetFramework ?? DefaultTargetFramework), "AppBundle");
-
- assertAppBundleOptions ??= new AssertTestMainJsAppBundleOptions(
- BundleDir: bundleDir,
- ProjectName: buildArgs.ProjectName,
- Config: buildArgs.Config,
- MainJS: buildProjectOptions.MainJS ?? "test-main.js",
- HasV8Script: buildProjectOptions.HasV8Script,
- GlobalizationMode: buildProjectOptions.GlobalizationMode,
- PredefinedIcudt: buildProjectOptions.PredefinedIcudt ?? "",
- UseWebcil: UseWebcil,
- IsBrowserProject: buildProjectOptions.IsBrowserProject,
- IsPublish: buildProjectOptions.Publish);
- new TestMainJsProjectProvider(_testOutput, _projectDir)
- .AssertBasicAppBundle(assertAppBundleOptions);
-
+ if (buildProjectOptions.AssertAppBundle)
+ AssertBundle(buildArgs, buildProjectOptions, res.Output, assertAppBundleOptions);
return (_projectDir!, res.Output);
}
+ public void AssertBundle(BuildArgs buildArgs,
+ BuildProjectOptions buildProjectOptions,
+ string? buildOutput = null,
+ AssertTestMainJsAppBundleOptions? assertAppBundleOptions = null)
+ {
+ if (buildOutput is not null)
+ ProjectProviderBase.AssertRuntimePackPath(buildOutput, buildProjectOptions.TargetFramework ?? DefaultTargetFramework);
+
+ // TODO: templates don't use wasm sdk yet
+ var testMainJsProvider = new TestMainJsProjectProvider(_testOutput, _projectDir!);
+ if (assertAppBundleOptions is not null)
+ testMainJsProvider.AssertBundle(assertAppBundleOptions);
+ else
+ testMainJsProvider.AssertBundle(buildArgs, buildProjectOptions);
+ }
}
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.WebAssembly.Pack.Tasks", "..\..\..\tasks\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.csproj", "{5EEC2925-2021-4830-B7E9-72BB8B2C283D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasi.Build.Tests", "..\..\wasi\Wasi.Build.Tests\Wasi.Build.Tests.csproj", "{3A3AEAE5-0110-45D3-89B0-B82AC430535C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{5EEC2925-2021-4830-B7E9-72BB8B2C283D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5EEC2925-2021-4830-B7E9-72BB8B2C283D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5EEC2925-2021-4830-B7E9-72BB8B2C283D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3A3AEAE5-0110-45D3-89B0-B82AC430535C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3A3AEAE5-0110-45D3-89B0-B82AC430535C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3A3AEAE5-0110-45D3-89B0-B82AC430535C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3A3AEAE5-0110-45D3-89B0-B82AC430535C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE