diff --git a/eng/Subsets.props b/eng/Subsets.props index 4f98634f6372e1..ccbe8268ab0c03 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -70,6 +70,7 @@ $(DefaultMonoSubsets)mono.aotcross+ $(DefaultMonoSubsets)mono.runtime+mono.corelib+mono.packages+ $(DefaultMonoSubsets)mono.manifests+ + $(DefaultMonoSubsets)mono.manifests+ $(DefaultMonoSubsets)mono.tools+ $(DefaultMonoSubsets)host.native+ @@ -153,6 +154,7 @@ + @@ -424,6 +426,10 @@ + + + + diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index e6a07c9b4c6033..41cce9e1534f94 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -31,6 +31,7 @@ parameters: extraStepsParameters: {} extraVariablesTemplates: [] isManualCodeQLBuild: false + preBuildSteps: [] jobs: - template: /eng/common/templates/job/job.yml @@ -183,6 +184,10 @@ jobs: inputs: filePath: $(Build.SourcesDirectory)/eng/pipelines/mono/update-machine-certs.ps1 + - ${{ if ne(parameters.preBuildSteps,'') }}: + - ${{ each preBuildStep in parameters.preBuildSteps }}: + - ${{ preBuildStep }} + # Build - ${{ if eq(parameters.isSourceBuild, false) }}: - ${{ if eq(parameters.isManualCodeQLBuild, true) }}: diff --git a/eng/pipelines/common/templates/browser-wasm-build-tests.yml b/eng/pipelines/common/templates/browser-wasm-build-tests.yml new file mode 100644 index 00000000000000..28d659e1607f48 --- /dev/null +++ b/eng/pipelines/common/templates/browser-wasm-build-tests.yml @@ -0,0 +1,126 @@ +# Depends on other builds to get runtime packs, and nugets +# And then runs Wasm.Build.Tests +parameters: + alwaysRun: false + isExtraPlatformsBuild: false + isWasmOnlyBuild: false + platforms: [] + shouldContinueOnError: false + extraBuildArgs: '' + +jobs: + +- ${{ each platform in parameters.platforms }}: + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - ${{ platform }} + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} + variables: + # map dependencies variables to local variables + - name: alwaysRunVar + value: ${{ parameters.alwaysRun }} + - name: workloadsTestPreviousVersionsVar + value: $[ + or( + eq(variables['Build.SourceBranchName'], 'main'), + eq(variables['System.PullRequest.TargetBranch'], 'main')) + ] + - name: wbtProjectArg + ${{ if eq(platform, 'browser_wasm_win') }}: + value: '-projects' + ${{ else }}: + value: '--projects' + - name: shouldRunOnDefaultPipelines + value: $(shouldRunWasmBuildTestsOnDefaultPipeline) + + jobParameters: + dependsOn: + - ${{ if eq(platform, 'browser_wasm') }}: + - build_browser_wasm_linux_Release_MultiThreaded_BuildOnly + - build_browser_wasm_linux_Release_SingleThreaded_BuildOnly + - ${{ if eq(platform, 'browser_wasm_win') }}: + - build_browser_wasm_windows_Release_MultiThreaded_BuildOnly + - build_browser_wasm_windows_Release_SingleThreaded_BuildOnly + isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} + testGroup: innerloop + nameSuffix: WasmBuildTests + + preBuildSteps: + # Download single threaded runtime packs, and tasks needed to build WBT + - task: DownloadBuildArtifacts@0 + displayName: Download built nugets for singlethreaded runtime + inputs: + buildType: current + artifactName: 'BuildArtifacts_browser_wasm_$(_hostedOs)_Release_SingleThreaded_BuildOnly' + downloadType: single + downloadPath: '$(Build.SourcesDirectory)/artifacts' + + - task: CopyFiles@2 + displayName: Copy single threaded assets + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/BuildArtifacts_browser_wasm_$(_hostedOs)_Release_SingleThreaded_BuildOnly' + TargetFolder: '$(Build.SourcesDirectory)/artifacts' + CleanTargetFolder: false + + # Download for multi-threaded + - task: DownloadBuildArtifacts@0 + displayName: Download built nugets for multi-threaded runtime + inputs: + buildType: current + artifactName: BuildArtifacts_browser_wasm_$(_hostedOs)_Release_MultiThreaded_BuildOnly + downloadType: single + downloadPath: '$(Build.SourcesDirectory)/artifacts' + + - task: CopyFiles@2 + displayName: Copy multithreading runtime pack + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/BuildArtifacts_browser_wasm_$(_hostedOs)_Release_MultiThreaded_BuildOnly' + Contents: packages/$(_BuildConfig)/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.* + TargetFolder: '$(Build.SourcesDirectory)/artifacts' + CleanTargetFolder: false + + # Download WBT + - task: DownloadBuildArtifacts@0 + displayName: Download Wasm.Build.Tests + inputs: + buildType: current + artifactName: WasmBuildTests_$(_hostedOs)_SingleThreaded_BuildOnly + downloadType: single + downloadPath: '$(Build.SourcesDirectory)/artifacts' + + - task: CopyFiles@2 + displayName: Copy Wasm.Build.Tests archive + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts/WasmBuildTests_$(_hostedOs)_SingleThreaded_BuildOnly' + Contents: helix/** + TargetFolder: '$(Build.SourcesDirectory)/artifacts' + CleanTargetFolder: false + + # build WBT + buildArgs: >- + $(wbtProjectArg) $(Build.SourcesDirectory)/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj + /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/Build.binlog + /p:Configuration=$(_BuildConfig) + /p:TestUsingWorkloads=true + /p:InstallWorkloadForTesting=true + /p:WasmSkipMissingRuntimePackBuild=true + /p:PreparePackagesForWorkloadInstall=false + timeoutInMinutes: 120 + condition: >- + or( + eq(variables['alwaysRunVar'], true), + eq(variables['isDefaultPipeline'], variables['shouldRunWasmBuildTestsOnDefaultPipeline'])) + + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:BrowserHost=$(_hostedOs) + scenarios: + - buildwasmapps diff --git a/eng/pipelines/common/templates/wasm-build-tests.yml b/eng/pipelines/common/templates/simple-wasm-build-tests.yml similarity index 79% rename from eng/pipelines/common/templates/wasm-build-tests.yml rename to eng/pipelines/common/templates/simple-wasm-build-tests.yml index db21f2fd34fff0..dcba5522f441b4 100644 --- a/eng/pipelines/common/templates/wasm-build-tests.yml +++ b/eng/pipelines/common/templates/simple-wasm-build-tests.yml @@ -1,3 +1,4 @@ +# run Wasm.Build.Tests with a single threading runtime parameters: alwaysRun: false isExtraPlatformsBuild: false @@ -9,7 +10,7 @@ parameters: jobs: # -# Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests +# Build the whole product using Mono and run Wasm.Build.Tests # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -29,13 +30,6 @@ jobs: eq(variables['Build.SourceBranchName'], 'main'), eq(variables['System.PullRequest.TargetBranch'], 'main')) ] - - name: shouldRunOnDefaultPipelines - value: $[ - or( - eq(variables['wasmDarcDependenciesChanged'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true)) - ] jobParameters: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} testGroup: innerloop @@ -45,7 +39,7 @@ jobs: condition: >- or( eq(variables['alwaysRunVar'], true), - eq(variables['isDefaultPipeline'], variables['shouldRunOnDefaultPipelines'])) + eq(variables['isDefaultPipeline'], variables['shouldRunWasmBuildTestsOnDefaultPipeline'])) # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: diff --git a/eng/pipelines/common/templates/wasm-build-only.yml b/eng/pipelines/common/templates/wasm-build-only.yml index 09107af2536522..9e9b0cb332c8fa 100644 --- a/eng/pipelines/common/templates/wasm-build-only.yml +++ b/eng/pipelines/common/templates/wasm-build-only.yml @@ -1,46 +1,44 @@ parameters: - alwaysRun: false + condition: false extraBuildArgs: '' isExtraPlatformsBuild: false nameSuffix: '' platforms: [] + publishArtifactsForWorkload: false + publishWBT: false jobs: # -# Build for Browser/wasm and test it +# Build for Browser/wasm # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml buildConfig: Release runtimeFlavor: mono platforms: ${{ parameters.platforms }} variables: # map dependencies variables to local variables - - name: alwaysRunVar - value: ${{ parameters.alwaysRun }} - - name: shouldRunOnDefaultPipelines - value: $[ - or( - eq(variables['wasmDarcDependenciesChanged'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_wasm_specific_except_wbt_dbg.containsChange'], true)) - ] + - name: workloadSubsetArg + ${{ if eq(parameters.publishArtifactsForWorkload, true) }}: + value: '+mono.wasmworkload' + ${{ else }}: + value: '' + - name: extraBuildArgs + ${{ if eq(parameters.publishWBT, true) }}: + value: /p:TestWasmBuildTests=true /p:ArchiveTests=true /p:InstallWorkloadForTesting=false + ${{ else }}: + value: '' + jobParameters: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} testGroup: innerloop nameSuffix: ${{ parameters.nameSuffix }}_BuildOnly - buildArgs: -s mono+libs+host -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=$(_hostedOs) ${{ parameters.extraBuildArgs }} - timeoutInMinutes: 240 - # if !alwaysRun, then: - # if this is runtime-wasm (isWasmOnlyBuild): - # - then run only if it would not have run on default pipelines (based - # on path changes) - # - else run based on path changes - condition: >- - or( - eq(variables['alwaysRunVar'], true), - eq(variables['isDefaultPipeline'], variables['shouldRunOnDefaultPipelines'])) + buildArgs: -s mono+libs+packs+libs.tests$(workloadSubsetArg) -c $(_BuildConfig) /p:BrowserHost=$(_hostedOs) ${{ parameters.extraBuildArgs }} /p:TestAssemblies=false $(extraBuildArgs) + timeoutInMinutes: 120 + condition: ${{ parameters.condition }} + extraStepsTemplate: /eng/pipelines/common/wasm-post-build-steps.yml + extraStepsParameters: + publishArtifactsForWorkload: ${{ parameters.publishArtifactsForWorkload }} + publishWBT: ${{ parameters.publishWBT }} diff --git a/eng/pipelines/common/wasm-post-build-steps.yml b/eng/pipelines/common/wasm-post-build-steps.yml new file mode 100644 index 00000000000000..2c7979ae25308d --- /dev/null +++ b/eng/pipelines/common/wasm-post-build-steps.yml @@ -0,0 +1,50 @@ +parameters: + nameSuffix: '' + buildConfig: '' + hostedOs: '' + osGroup: '' + publishArtifactsForWorkload: always() + publishWBT: always() + +steps: + + - task: CopyFiles@2 + displayName: Copy artifacts needed for running WBT + condition: and(succeeded(), ${{ parameters.publishArtifactsForWorkload }}) + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts' + Contents: | + packages/$(_BuildConfig)/Shipping/** + packages/$(_BuildConfig)/NonShipping/** + bin/WasmAppBuilder/**/* + bin/WasmBuildTasks/** + bin/WorkloadBuildTasks/** + bin/installer.tasks/** + bin/Crossgen2Tasks/** + TargetFolder: '$(Build.StagingDirectory)/IntermediateArtifacts' + CleanTargetFolder: true + + - task: PublishBuildArtifacts@1 + displayName: Publish intermediate artifacts + condition: and(succeeded(), ${{ parameters.publishArtifactsForWorkload }}) + inputs: + pathToPublish: '$(Build.StagingDirectory)/IntermediateArtifacts' + artifactName: BuildArtifacts_${{ parameters.osGroup }}_wasm_$(_hostedOs)_${{ parameters.buildConfig }}_${{ parameters.nameSuffix }} + artifactType: container + + - task: CopyFiles@2 + displayName: Copy WBT + condition: and(succeeded(), ${{ parameters.publishWBT }}) + inputs: + SourceFolder: '$(Build.SourcesDirectory)/artifacts' + Contents: helix/buildwasmapps/** + TargetFolder: '$(Build.StagingDirectory)/IntermediateArtifacts' + CleanTargetFolder: true + + - task: PublishBuildArtifacts@1 + displayName: Publish Wasm.Build.Tests archive + condition: and(succeeded(), ${{ parameters.publishWBT }}) + inputs: + pathToPublish: '$(Build.StagingDirectory)/IntermediateArtifacts' + artifactName: WasmBuildTests_$(_hostedOs)_${{ parameters.nameSuffix }} + artifactType: container diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index b56f65ef76ce52..b2227d0c42eba7 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -105,8 +105,8 @@ jobs: ${{ if eq(parameters.jobParameters.runtimeFlavor, 'coreclr') }}: value: CoreCLR - - name: wasmDarcDependenciesChanged - ${{ if eq(parameters.archType, 'wasm') }}: + - ${{ if eq(parameters.archType, 'wasm') }}: + - name: wasmDarcDependenciesChanged value: $[ or( eq(dependencies.evaluate_paths.outputs['DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-8_0_100_Transport'], true), eq(dependencies.evaluate_paths.outputs['DarcDependenciesChanged.Microsoft_DotNet_Build_Tasks_Workloads'], true), @@ -118,6 +118,20 @@ jobs: eq(dependencies.evaluate_paths.outputs['DarcDependenciesChanged.Microsoft_CodeAnalysis_NetAnalyzers'], true), eq(dependencies.evaluate_paths.outputs['DarcDependenciesChanged.Microsoft_NET_ILLink_Tasks'], true)) ] + - name: shouldRunWasmBuildTestsOnDefaultPipeline + value: $[ + or( + eq(variables['wasmDarcDependenciesChanged'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true)) + ] + + # needed for Wasm.Build.Tests + - name: wasmSingleThreadedBuildOnlyNeededOnDefaultPipeline + value: $[ variables['shouldRunWasmBuildTestsOnDefaultPipeline'] ] + - name: wasmMultiThreadedBuildOnlyNeededOnDefaultPipeline + value: $[ variables['shouldRunWasmBuildTestsOnDefaultPipeline'] ] + - ${{ each variable in parameters.variables }}: - ${{ variable }} diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index 876827fab1887d..3fe2e54610d925 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -196,12 +196,40 @@ jobs: - normal - ${{ if and(ne(parameters.isRollingBuild, true), ne(parameters.excludeNonLibTests, true), ne(parameters.debuggerTestsOnly, true)) }}: - # Wasm.Build.Tests - - template: /eng/pipelines/common/templates/wasm-build-tests.yml + # Builds only + - template: /eng/pipelines/common/templates/wasm-build-only.yml parameters: platforms: - browser_wasm - browser_wasm_win + nameSuffix: SingleThreaded + extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + condition: ne(variables['wasmSingleThreadedBuildOnlyNeededOnDefaultPipeline'], true) + publishArtifactsForWorkload: true + publishWBT: true + + - template: /eng/pipelines/common/templates/wasm-build-only.yml + parameters: + platforms: + - browser_wasm + - browser_wasm_win + nameSuffix: MultiThreaded + extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + condition: ne(variables['wasmMultiThreadedBuildOnlyNeededOnDefaultPipeline'], true) + publishArtifactsForWorkload: true + publishWBT: false + + # Browser Wasm.Build.Tests + - template: /eng/pipelines/common/templates/browser-wasm-build-tests.yml + parameters: + platforms: + - browser_wasm + - browser_wasm_win + extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + + - template: /eng/pipelines/common/templates/simple-wasm-build-tests.yml + parameters: + platforms: - wasi_wasm - wasi_wasm_win extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index ade994eb08c6a7..e83381f19cc1c0 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -472,8 +472,31 @@ extends: shouldRunSmokeOnly: true alwaysRun: ${{ variables.isRollingBuild }} - # Wasm.Build.Tests - - template: /eng/pipelines/common/templates/wasm-build-tests.yml + # For Wasm.Build.Tests - runtime pack builds + - template: /eng/pipelines/common/templates/wasm-build-only.yml + parameters: + platforms: + - browser_wasm + - browser_wasm_win + condition: or(eq(variables.isRollingBuild, true), eq(variables.wasmSingleThreadedBuildOnlyNeededOnDefaultPipeline, true)) + nameSuffix: SingleThreaded + extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + publishArtifactsForWorkload: true + publishWBT: true + + - template: /eng/pipelines/common/templates/wasm-build-only.yml + parameters: + platforms: + - browser_wasm + - browser_wasm_win + condition: or(eq(variables.isRollingBuild, true), eq(variables.wasmSingleThreadedBuildOnlyNeededOnDefaultPipeline, true)) + nameSuffix: MultiThreaded + extraBuildArgs: /p:MonoWasmBuildVariant=multithread /p:WasmEnableThreads=true /p:_WasmPThreadPoolSize=8 /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + publishArtifactsForWorkload: true + publishWBT: false + + # Browser Wasm.Build.Tests + - template: /eng/pipelines/common/templates/browser-wasm-build-tests.yml parameters: platforms: - browser_wasm @@ -525,7 +548,7 @@ extends: scenarios: - normal - - template: /eng/pipelines/common/templates/wasm-build-tests.yml + - template: /eng/pipelines/common/templates/simple-wasm-build-tests.yml parameters: platforms: - wasi_wasm diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 356cf2e3be5262..cc16b81fa55b70 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -35,3 +35,4 @@ Wasm.Build.Tests.WasmSIMDTests Wasm.Build.Tests.WasmTemplateTests Wasm.Build.Tests.WorkloadTests Wasm.Build.Tests.TestAppScenarios.DownloadResourceProgressTests +Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests diff --git a/eng/testing/workloads-testing.targets b/eng/testing/workloads-testing.targets index 541e476fad3d9a..373ee0d388a04e 100644 --- a/eng/testing/workloads-testing.targets +++ b/eng/testing/workloads-testing.targets @@ -9,6 +9,7 @@ <_SdkForWorkloadTestingBasePath>$(ArtifactsBinDir) <_SdkWithNoWorkloadPath>$([MSBuild]::NormalizeDirectory($(_SdkForWorkloadTestingBasePath), 'dotnet-none')) <_SdkWithNoWorkloadStampPath>$([MSBuild]::NormalizePath($(_SdkWithNoWorkloadPath), '.version-for-none-$(SdkVersionForWorkloadTesting).stamp')) + true $(InstallWorkloadUsingArtifactsDependsOn); _ProvisionDotNetForWorkloadTesting; @@ -157,7 +158,7 @@ DependsOnTargets="$(InstallWorkloadUsingArtifactsDependsOn)" Condition="'$(InstallWorkloadForTesting)' == 'true'" /> - + <_NuGetsToBuild Include="$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Ref.$(PackageVersionForWorkloadManifests).nupkg" Project="$(InstallerProjectRoot)pkg/sfx/Microsoft.NETCore.App\Microsoft.NETCore.App.Ref.sfxproj" @@ -166,7 +167,7 @@ - + diff --git a/src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs b/src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs index 2cd6c1a2621151..f83eaf616958f7 100644 --- a/src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs +++ b/src/mono/wasm/Wasm.Build.Tests/AssertWasmSdkBundleOptions.cs @@ -12,7 +12,7 @@ public record AssertWasmSdkBundleOptions( string TargetFramework, string BinFrameworkDir, string? PredefinedIcudt, - GlobalizationMode GlobalizationMode = GlobalizationMode.Default, + GlobalizationMode GlobalizationMode = GlobalizationMode.Sharded, string BootJsonFileName = "blazor.boot.json", NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack, RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded, diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs index 8f3d7b8ee28aeb..0304d9f113c70a 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/AppsettingsTests.cs @@ -43,12 +43,16 @@ var builder bool existsChecked = false; bool contentChecked = false; - await BlazorRunForBuildWithDotnetRun("debug", onConsoleMessage: msg => + await BlazorRunForBuildWithDotnetRun(new BlazorRunOptions() { - if (msg.Text.Contains("appSettings Exists 'True'")) - existsChecked = true; - else if (msg.Text.Contains($"appSettings Content '{{ \"Id\": \"{id}\" }}'")) - contentChecked = true; + Config = "debug", + OnConsoleMessage = msg => + { + if (msg.Text.Contains("appSettings Exists 'True'")) + existsChecked = true; + else if (msg.Text.Contains($"appSettings Content '{{ \"Id\": \"{id}\" }}'")) + contentChecked = true; + } }); Assert.True(existsChecked, "File '/appsettings.json' wasn't found"); diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorRunOptions.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorRunOptions.cs new file mode 100644 index 00000000000000..4dac97ebb0c7f8 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorRunOptions.cs @@ -0,0 +1,23 @@ +// 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.Threading.Tasks; +using Microsoft.Playwright; + +#nullable enable + +namespace Wasm.Build.Tests.Blazor; +public record BlazorRunOptions +( + BlazorRunHost Host = BlazorRunHost.DotnetRun, + bool DetectRuntimeFailures = true, + bool CheckCounter = true, + Func? Test = null, + Action? OnConsoleMessage = null, + Action? OnErrorMessage = null, + string Config = "Debug", + string? ExtraArgs = null +); + +public enum BlazorRunHost { DotnetRun, WebServer }; diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs index f29e99fd568bc7..5372aa0d3e9d7c 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmProjectProvider.cs @@ -19,7 +19,7 @@ public void AssertBundle(BlazorBuildOptions options) IsPublish: options.IsPublish, TargetFramework: options.TargetFramework, BinFrameworkDir: FindBinFrameworkDir(options.Config, options.IsPublish, options.TargetFramework), - GlobalizationMode: GlobalizationMode.Default, + GlobalizationMode: GlobalizationMode.Sharded, PredefinedIcudt: null, ExpectFingerprintOnDotnetJs: options.ExpectFingerprintOnDotnetJs, ExpectedFileType: options.ExpectedFileType, diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs index da4a414b338fbb..82ce0dd906123e 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BlazorWasmTestBase.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.Playwright; +using Wasm.Build.Tests.Blazor; using Xunit; using Xunit.Abstractions; using Xunit.Sdk; @@ -124,7 +125,7 @@ public void AssertBundle(string buildOutput, BlazorBuildOptions blazorBuildOptio if (IsUsingWorkloads) { // In no-workload case, the path would be from a restored nuget - ProjectProviderBase.AssertRuntimePackPath(buildOutput, blazorBuildOptions.TargetFramework ?? DefaultTargetFramework); + ProjectProviderBase.AssertRuntimePackPath(buildOutput, blazorBuildOptions.TargetFramework ?? DefaultTargetFramework, blazorBuildOptions.RuntimeType); } _provider.AssertBundle(blazorBuildOptions); @@ -146,49 +147,71 @@ protected string CreateProjectWithNativeReference(string id) // Keeping these methods with explicit Build/Publish in the name // so in the test code it is evident which is being run! - public Task BlazorRunForBuildWithDotnetRun(string config, Func? test = null, string extraArgs = "--no-build", Action? onConsoleMessage = null) - => BlazorRunTest($"run -c {config} {extraArgs}", _projectDir!, test, onConsoleMessage); + public Task BlazorRunForBuildWithDotnetRun(BlazorRunOptions runOptions) + { + if (runOptions.ExtraArgs is null) + runOptions = runOptions with { ExtraArgs = "--no-build" }; + + return BlazorRunTest($"run -c {runOptions.Config}", + _projectDir!, + runOptions with { Host = BlazorRunHost.DotnetRun }); + } - public Task BlazorRunForPublishWithWebServer(string config, Func? test = null, string extraArgs = "", Action? onConsoleMessage = null) - => BlazorRunTest($"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files {extraArgs}", - Path.GetFullPath(Path.Combine(FindBlazorBinFrameworkDir(config, forPublish: true), "..")), - test, onConsoleMessage); + public Task BlazorRunForPublishWithWebServer(BlazorRunOptions runOptions) + => BlazorRunTest($"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files", + Path.GetFullPath(Path.Combine(FindBlazorBinFrameworkDir(runOptions.Config, forPublish: true), "..")), + runOptions with { Host = BlazorRunHost.WebServer }); public async Task BlazorRunTest(string runArgs, string workingDirectory, - Func? test = null, - Action? onConsoleMessage = null, - bool detectRuntimeFailures = true) + BlazorRunOptions runOptions) { + if (!string.IsNullOrEmpty(runOptions.ExtraArgs)) + runArgs += $" {runOptions.ExtraArgs}"; using var runCommand = new RunCommand(s_buildEnv, _testOutput) .WithWorkingDirectory(workingDirectory); await using var runner = new BrowserRunner(_testOutput); - var page = await runner.RunAsync(runCommand, runArgs, onConsoleMessage: OnConsoleMessage); + var page = await runner.RunAsync(runCommand, runArgs, onConsoleMessage: OnConsoleMessage, onError: OnErrorMessage); + + _testOutput.WriteLine("Waiting for page to load"); + await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + + if (runOptions.CheckCounter) + { + await page.Locator("text=Counter").ClickAsync(); + var txt = await page.Locator("p[role='status']").InnerHTMLAsync(); + Assert.Equal("Current count: 0", txt); - await page.Locator("text=Counter").ClickAsync(); - var txt = await page.Locator("p[role='status']").InnerHTMLAsync(); - Assert.Equal("Current count: 0", txt); + await page.Locator("text=\"Click me\"").ClickAsync(); + txt = await page.Locator("p[role='status']").InnerHTMLAsync(); + Assert.Equal("Current count: 1", txt); + } - await page.Locator("text=\"Click me\"").ClickAsync(); - txt = await page.Locator("p[role='status']").InnerHTMLAsync(); - Assert.Equal("Current count: 1", txt); + if (runOptions.Test is not null) + await runOptions.Test(page); - if (test is not null) - await test(page); + _testOutput.WriteLine($"Waiting for additional 10secs to see if any errors are reported"); + await Task.Delay(10_000); void OnConsoleMessage(IConsoleMessage msg) { _testOutput.WriteLine($"[{msg.Type}] {msg.Text}"); - onConsoleMessage?.Invoke(msg); + runOptions.OnConsoleMessage?.Invoke(msg); - if (detectRuntimeFailures) + if (runOptions.DetectRuntimeFailures) { if (msg.Text.Contains("[MONO] * Assertion") || msg.Text.Contains("Error: [MONO] ")) throw new XunitException($"Detected a runtime failure at line: {msg.Text}"); } } + + void OnErrorMessage(string msg) + { + _testOutput.WriteLine($"[ERROR] {msg}"); + runOptions.OnErrorMessage?.Invoke(msg); + } } public string FindBlazorBinFrameworkDir(string config, bool forPublish, string framework = DefaultTargetFrameworkForBlazor) diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs index 520dc8d05c8b94..589f87d6969e80 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs @@ -31,10 +31,10 @@ public async Task DefaultTemplate_WithoutWorkload(string config) CreateBlazorWasmTemplateProject(id); BlazorBuild(new BlazorBuildOptions(id, config)); - await BlazorRunForBuildWithDotnetRun(config); + await BlazorRunForBuildWithDotnetRun(new BlazorRunOptions() { Config = config }); BlazorPublish(new BlazorBuildOptions(id, config)); - await BlazorRunForPublishWithWebServer(config); + await BlazorRunForPublishWithWebServer(new BlazorRunOptions() { Config = config }); } [Theory] @@ -155,10 +155,11 @@ public static class MyDllImports if (publish) BlazorPublish(new BlazorBuildOptions(id, config, NativeFilesType.Relinked, ExpectRelinkDirWhenPublishing: build)); + BlazorRunOptions runOptions = new() { Config = config, Test = TestDllImport }; if (publish) - await BlazorRunForPublishWithWebServer(config, TestDllImport); + await BlazorRunForPublishWithWebServer(runOptions); else - await BlazorRunForBuildWithDotnetRun(config, TestDllImport); + await BlazorRunForBuildWithDotnetRun(runOptions); async Task TestDllImport(IPage page) { @@ -230,7 +231,7 @@ public async Task BlazorBuildRunTest(string config) string projectFile = CreateWasmTemplateProject(id, "blazorwasm"); BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack)); - await BlazorRunForBuildWithDotnetRun(config); + await BlazorRunForBuildWithDotnetRun(new BlazorRunOptions() { Config = config }); } [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] @@ -250,7 +251,7 @@ public async Task BlazorPublishRunTest(string config, bool aot) config, aot ? NativeFilesType.AOT : (config == "Release" ? NativeFilesType.Relinked : NativeFilesType.FromRuntimePack))); - await BlazorRunForPublishWithWebServer(config); + await BlazorRunForPublishWithWebServer(new BlazorRunOptions() { Config = config }); } private void BlazorAddRazorButton(string buttonText, string customCode, string methodName = "test", string razorPage = "Pages/Counter.razor") diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs new file mode 100644 index 00000000000000..f430c235a12fbc --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/SimpleMultiThreadedTests.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Wasm.Build.Tests.Blazor; +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +#nullable enable + +namespace Wasm.Build.Tests.MT.Blazor; + +public class SimpleMultiThreadedTests : BlazorWasmTestBase +{ + public SimpleMultiThreadedTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + // dotnet-run needed for running with *build* so wwwroot has the index.html etc + // [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] + // [InlineData("Debug")] + // [InlineData("Release")] + // public async Task BlazorBuildRunTest(string config) + // { + // string id = $"blazor_mt_{config}_{Path.GetRandomFileName()}"; + // string projectFile = CreateWasmTemplateProject(id, "blazorwasm"); + + // AddItemsPropertiesToProject(projectFile, "true"); + // BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.FromRuntimePack, RuntimeType: RuntimeType.MultiThreaded)); + // // await BlazorRunForBuildWithDotnetRun(config); + + // await BlazorRunTest($"{s_xharnessRunnerCommand} wasm webserver --app=. --web-server-use-default-files --web-server-use-cors --web-server-use-cop --web-server-use-https --timeout=15:00:00", + // Path.GetFullPath(Path.Combine(FindBlazorBinFrameworkDir(config, forPublish: false), ".."))); + // } + + [ConditionalTheory(typeof(BuildTestBase), nameof(IsWorkloadWithMultiThreadingForDefaultFramework))] + [InlineData("Debug", false)] + // [InlineData("Debug", true)] + [InlineData("Release", false)] + // [InlineData("Release", true)] + public async Task BlazorPublishRunTest(string config, bool aot) + { + string id = $"blazor_mt_{config}_{Path.GetRandomFileName()}"; + string projectFile = CreateWasmTemplateProject(id, "blazorwasm"); + AddItemsPropertiesToProject(projectFile, "true"); + // if (aot) + // AddItemsPropertiesToProject(projectFile, "true"); + + BlazorPublish(new BlazorBuildOptions( + id, + config, + aot ? NativeFilesType.AOT + : (config == "Release" ? NativeFilesType.Relinked : NativeFilesType.FromRuntimePack), + RuntimeType: RuntimeVariant.MultiThreaded)); + + StringBuilder errorOutput = new(); + await BlazorRunForPublishWithWebServer( + runOptions: new BlazorRunOptions( + Config: config, + ExtraArgs: "--web-server-use-cors --web-server-use-cop", + OnConsoleMessage: (message) => + { + if (message.Type == "error") + errorOutput.AppendLine(message.Text); + }, + OnErrorMessage: (message) => + { + errorOutput.AppendLine(message); + })); + + if (errorOutput.Length > 0) + throw new XunitException($"Errors found in browser console output:\n{errorOutput}"); + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs index f12bef8ce53155..d72a844abf1e78 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BrowserRunner.cs @@ -35,7 +35,13 @@ internal class BrowserRunner : IAsyncDisposable public BrowserRunner(ITestOutputHelper testOutput) => _testOutput = testOutput; // FIXME: options - public async Task RunAsync(ToolCommand cmd, string args, bool headless = true, Action? onConsoleMessage = null, Func? modifyBrowserUrl = null) + public async Task RunAsync( + ToolCommand cmd, + string args, + bool headless = true, + Action? onConsoleMessage = null, + Action? onError = null, + Func? modifyBrowserUrl = null) { TaskCompletionSource urlAvailable = new(); Action outputHandler = msg => @@ -96,6 +102,15 @@ public async Task RunAsync(ToolCommand cmd, string args, bool headless = IPage page = await Browser.NewPageAsync(); if (onConsoleMessage is not null) page.Console += (_, msg) => onConsoleMessage(msg); + + onError ??= _testOutput.WriteLine; + if (onError is not null) + { + page.PageError += (_, msg) => onError($"PageError: {msg}"); + page.Crash += (_, msg) => onError($"Crash: {msg}"); + page.FrameDetached += (_, msg) => onError($"FrameDetached: {msg}"); + } + await page.GotoAsync(browserUrl); RunTask = runTask; return page; diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildProjectOptions.cs b/src/mono/wasm/Wasm.Build.Tests/BuildProjectOptions.cs index 0f666a5e04f8c7..438dd1e9616576 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildProjectOptions.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildProjectOptions.cs @@ -12,7 +12,7 @@ public record BuildProjectOptions ( Action? InitProject = null, bool? DotnetWasmFromRuntimePack = null, - GlobalizationMode GlobalizationMode = GlobalizationMode.Default, + GlobalizationMode GlobalizationMode = GlobalizationMode.Sharded, string? PredefinedIcudt = null, bool UseCache = true, bool ExpectSuccess = true, diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs index 77b0ae861ba561..352a9dcb1306f2 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs @@ -50,6 +50,7 @@ public abstract class BuildTestBase : IClassFixture s_buildEnv.IsWorkload; public static bool IsNotUsingWorkloads => !s_buildEnv.IsWorkload; + public static bool IsWorkloadWithMultiThreadingForDefaultFramework => s_buildEnv.IsWorkloadWithMultiThreadingForDefaultFramework; public static bool UseWebcil => s_buildEnv.UseWebcil; public static string GetNuGetConfigPathFor(string targetFramework) => Path.Combine(BuildEnvironment.TestDataPath, "nuget8.config"); // for now - we are still using net7, but with @@ -84,6 +85,7 @@ static BuildTestBase() Console.WriteLine($"=============== Using webcil-in-wasm ==============="); else Console.WriteLine($"=============== Webcil disabled ==============="); + Console.WriteLine ($"============== Multi-threading runtime pack for {DefaultTargetFramework} is {(IsWorkloadWithMultiThreadingForDefaultFramework ? "available" : "not available")} =============="); Console.WriteLine($"=============================================================================================="); Console.WriteLine(""); } diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/AssertBundleOptionsBase.cs b/src/mono/wasm/Wasm.Build.Tests/Common/AssertBundleOptionsBase.cs index 807659d849775f..e985ebf458938b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/AssertBundleOptionsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/AssertBundleOptionsBase.cs @@ -14,7 +14,7 @@ public abstract record AssertBundleOptionsBase( string BinFrameworkDir, string? PredefinedIcudt, string BundleDirName = "wwwroot", - GlobalizationMode GlobalizationMode = GlobalizationMode.Default, + GlobalizationMode GlobalizationMode = GlobalizationMode.Sharded, string BootJsonFileName = "blazor.boot.json", NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack, RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded, diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs b/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs index aa016743147229..a7b028164d3cc6 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/AssertTestMainJsAppBundleOptions.cs @@ -13,7 +13,7 @@ public record AssertTestMainJsAppBundleOptions( string? PredefinedIcudt, string ProjectName, string MainJS, - GlobalizationMode GlobalizationMode = GlobalizationMode.Default, + GlobalizationMode GlobalizationMode = GlobalizationMode.Sharded, string BootJsonFileName = "blazor.boot.json", NativeFilesType ExpectedFileType = NativeFilesType.FromRuntimePack, RuntimeVariant RuntimeType = RuntimeVariant.SingleThreaded, diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs b/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs index 9c062b0a9d7c0c..af97ed0c0726ee 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/BuildEnvironment.cs @@ -24,6 +24,8 @@ public class BuildEnvironment public string BuiltNuGetsPath { get; init; } public bool UseWebcil { get; init; } + public bool IsWorkloadWithMultiThreadingForDefaultFramework { get; init; } + public bool IsRunningOnCI => EnvironmentVariables.IsRunningOnCI; public static readonly string RelativeTestAssetsPath = @"..\testassets\"; public static readonly string TestAssetsPath = Path.Combine(AppContext.BaseDirectory, "testassets"); @@ -95,6 +97,14 @@ public BuildEnvironment() DirectoryBuildTargetsContents = s_directoryBuildTargetsForLocal; } + IsWorkloadWithMultiThreadingForDefaultFramework = IsMultiThreadingRuntimePackAvailableFor(BuildTestBase.DefaultTargetFramework); + if (IsWorkload && EnvironmentVariables.IsRunningOnCI && !IsWorkloadWithMultiThreadingForDefaultFramework) + { + throw new Exception( + "Expected the multithreading runtime pack to be available when running on CI." + + $" {nameof(IsRunningOnCI)} is true but {nameof(IsWorkloadWithMultiThreadingForDefaultFramework)} is false."); + } + UseWebcil = EnvironmentVariables.UseWebcil; if (EnvironmentVariables.BuiltNuGetsPath is null || !Directory.Exists(EnvironmentVariables.BuiltNuGetsPath)) @@ -147,6 +157,8 @@ runtimeType is RuntimeVariant.SingleThreaded GetRuntimePackVersion(tfm)); public string GetRuntimeNativeDir(string tfm = BuildTestBase.DefaultTargetFramework, RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded) => Path.Combine(GetRuntimePackDir(tfm, runtimeType), "runtimes", DefaultRuntimeIdentifier, "native"); + public bool IsMultiThreadingRuntimePackAvailableFor(string tfm) + => IsWorkload && File.Exists(Path.Combine(GetRuntimeNativeDir(tfm, RuntimeVariant.MultiThreaded), "dotnet.native.worker.js")); protected static string s_directoryBuildPropsForWorkloads = File.ReadAllText(Path.Combine(TestDataPath, "Workloads.Directory.Build.props")); protected static string s_directoryBuildTargetsForWorkloads = File.ReadAllText(Path.Combine(TestDataPath, "Workloads.Directory.Build.targets")); diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs b/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs index d29e9677fcac8b..80a1c67f9249e4 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/EnvironmentVariables.cs @@ -21,5 +21,6 @@ internal static class EnvironmentVariables internal static readonly bool UseWebcil = Environment.GetEnvironmentVariable("USE_WEBCIL_FOR_TESTS") is "true"; internal static readonly string? SdkDirName = Environment.GetEnvironmentVariable("SDK_DIR_NAME"); internal static readonly string? WasiSdkPath = Environment.GetEnvironmentVariable("WASI_SDK_PATH"); + internal static readonly bool IsRunningOnCI = Environment.GetEnvironmentVariable("IS_RUNNING_ON_CI") is "true"; } } diff --git a/src/mono/wasm/Wasm.Build.Tests/Common/GlobalizationMode.cs b/src/mono/wasm/Wasm.Build.Tests/Common/GlobalizationMode.cs index 29fee6d77db442..2710589c185d84 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Common/GlobalizationMode.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Common/GlobalizationMode.cs @@ -6,7 +6,7 @@ namespace Wasm.Build.Tests; public enum GlobalizationMode { - Default, // chosen based on locale + Sharded, // 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 diff --git a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs index d388c223d6e743..4da328f69ee2fb 100644 --- a/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/IcuShardingTests.cs @@ -226,7 +226,7 @@ public void FullIcuFromRuntimePackWithInvariant(BuildArgs buildArgs, bool invari new BuildProjectOptions( InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, - GlobalizationMode: invariant ? GlobalizationMode.Invariant : fullIcu ? GlobalizationMode.FullIcu : GlobalizationMode.Default)); + GlobalizationMode: invariant ? GlobalizationMode.Invariant : fullIcu ? GlobalizationMode.FullIcu : GlobalizationMode.Sharded)); string runOutput = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: host, id: id); } diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs index 43c0f63c9580f3..25f16fca67af4b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs @@ -59,7 +59,7 @@ private void TestInvariantGlobalization(BuildArgs buildArgs, bool? invariantGlob 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 : GlobalizationMode.Default)); + GlobalizationMode: invariantGlobalization == true ? GlobalizationMode.Invariant : GlobalizationMode.Sharded)); if (invariantGlobalization == true) { diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs index ceb63b992c626e..956e1ca4e8b99c 100644 --- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs @@ -54,7 +54,7 @@ public NativeRebuildTestsBase(ITestOutputHelper output, SharedBuildPerTestClassF new BuildProjectOptions( InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), DotnetWasmFromRuntimePack: false, - GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Default, + GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Sharded, CreateProject: true)); RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: RunHost.Chrome, id: id); @@ -87,7 +87,7 @@ protected string Rebuild(bool nativeRelink, bool invariant, BuildArgs buildArgs, id: id, new BuildProjectOptions( DotnetWasmFromRuntimePack: false, - GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Default, + GlobalizationMode: invariant ? GlobalizationMode.Invariant : GlobalizationMode.Sharded, CreateProject: false, UseCache: false, Verbosity: verbosity)); diff --git a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs index ccdf07d0458e23..1b571327dfd0ff 100644 --- a/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs @@ -170,7 +170,7 @@ private void AssertDotNetFilesSet( { bool expectFingerprint = superSet[expectedFilename]; - 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}"); + Assert.True(actual.ContainsKey(expectedFilename), $"Could not find {expectedFilename} in bundle directory: {bundleDir}. Actual files on disk: {string.Join(", ", actual.Keys)}"); // Check that the version and hash are present or not present as expected if (ShouldCheckFingerprint(expectedFilename: expectedFilename, @@ -320,13 +320,13 @@ public static bool ShouldCheckFingerprint(string expectedFilename, bool expectFi (expectedFilename == "dotnet.js" && expectFingerprintOnDotnetJs) || expectFingerprintForThisFile; - public static void AssertRuntimePackPath(string buildOutput, string targetFramework) + public static void AssertRuntimePackPath(string buildOutput, string targetFramework, RuntimeVariant runtimeType = RuntimeVariant.SingleThreaded) { var match = s_runtimePackPathRegex.Match(buildOutput); if (!match.Success || match.Groups.Count != 2) throw new XunitException($"Could not find the pattern in the build output: '{s_runtimePackPathPattern}'.{Environment.NewLine}Build output: {buildOutput}"); - string expectedRuntimePackDir = BuildTestBase.s_buildEnv.GetRuntimePackDir(targetFramework); + string expectedRuntimePackDir = BuildTestBase.s_buildEnv.GetRuntimePackDir(targetFramework, runtimeType); string actualPath = match.Groups[1].Value; if (string.Compare(actualPath, expectedRuntimePackDir) != 0) throw new XunitException($"Runtime pack path doesn't match.{Environment.NewLine}Expected: '{expectedRuntimePackDir}'{Environment.NewLine}Actual: '{actualPath}'"); @@ -365,7 +365,7 @@ public void AssertIcuAssets(AssertBundleOptionsBase assertOptions) // predefined ICU name can be identical with the icu files from runtime pack expected.Add(assertOptions.PredefinedIcudt); break; - case GlobalizationMode.Default: + case GlobalizationMode.Sharded: // icu shard chosen based on the locale expected.Add("icudt_CJK.dat"); expected.Add("icudt_EFIGS.dat"); diff --git a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj index c00042c7f0e799..d5059f1d5f432e 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -57,6 +57,9 @@ + + + diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs index aee3d0e9bf8df5..a76aaee38a929b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTestBase.cs @@ -22,7 +22,6 @@ protected WasmTemplateTestBase(ITestOutputHelper output, SharedBuildPerTestClass 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"), ""); diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index ba181982935c46..c5300db4ea8653 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -358,9 +358,9 @@ Condition="'$(WasmEmitSymbolMap)' == 'true' and '$(_HasDotnetJsSymbols)' != 'true' and Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.js.symbols')" /> - - diff --git a/src/mono/wasm/wasm.code-workspace b/src/mono/wasm/wasm.code-workspace index 80a990415ad601..6d95a8e6dd280a 100644 --- a/src/mono/wasm/wasm.code-workspace +++ b/src/mono/wasm/wasm.code-workspace @@ -14,6 +14,7 @@ "omnisharp.enableMsBuildLoadProjectsOnDemand": true, "omnisharp.defaultLaunchSolution": "${workspaceFolder}sln/WasmBuild.sln", "omnisharp.enableRoslynAnalyzers": true, - "cSpell.enabled": false + "cSpell.enabled": false, + "dotnet.defaultSolution": "wasm/sln/WasmBuild.sln" } } diff --git a/src/mono/wasm/workloads.proj b/src/mono/wasm/workloads.proj new file mode 100644 index 00000000000000..4c8e6943618983 --- /dev/null +++ b/src/mono/wasm/workloads.proj @@ -0,0 +1,20 @@ + + + + + <_DefaultPropsForNuGetBuild Include="Configuration=$(Configuration)" /> + <_DefaultPropsForNuGetBuild Include="TargetOS=$(TargetOS)" /> + <_DefaultPropsForNuGetBuild Include="TargetArchitecture=$(TargetArchitecture)" /> + <_DefaultPropsForNuGetBuild Include="ContinuousIntegrationBuild=$(ContinuousIntegrationBuild)" /> + + + <_PropsForAOTCrossBuild Include="@(_DefaultPropsForNuGetBuild)" /> + <_PropsForAOTCrossBuild Include="TestingWorkloads=true" /> + <_PropsForAOTCrossBuild Include="RuntimeIdentifier=$(NETCoreSdkRuntimeIdentifier)" /> + <_PropsForAOTCrossBuild Include="TargetCrossRid=browser-wasm" /> + <_PropsForAOTCrossBuild Include="DisableSourceLink=true" /> + + + +