Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison by pavelsavara · Pull Request #130616 · dotnet/runtime · GitHub
Skip to content

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison - #130616

Merged
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen
Jul 14, 2026
Merged

[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparison#130616
lewing merged 2 commits into
dotnet:mainfrom
pavelsavara:fix-wbt-referencenewassembly-drivergen

Conversation

@pavelsavara

@pavelsavarapavelsavara commented Jul 13, 2026

Copy link
Copy Markdown
Member

Fixes#130540

This PR fixes Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly, which had two independent problems: the AOT case (driver-gen.c not regenerated) and, once that was fixed, the relink case (dotnet.native.wasm size mismatch against a stale published file).

Fix 1 — driver-gen.c not regenerated (AOT case)

Problem

ReferenceNewAssembly(config: Release, aot: True, ...) fails deterministically with:

CompareStat failed:
[Expected changed file: driver-gen.c]

Root cause

driver-gen.c is the AOT modules table, written by MonoAOTCompiler.GenerateAotModulesTable via Utils.CopyIfDifferent(..., useHash: false). It is only rewritten (its timestamp bumped) when the content differs. The content is the ordered list of mono_aot_module__info symbols — i.e. the set of AOT-compiled assemblies.

The test replaces Common/Program.cs with NativeRebuildNewAssembly.cs, which used System.Security.Cryptography (SHA256), expecting that to add a new assembly to the AOT set so driver-gen.c would be regenerated.

However, WasmBasicTestAppalready pulls System.Security.Cryptography into its closure in both builds, via HttpTest.cs ([JSExport]HttpClientSystem.Net.Http → crypto) and ZipArchiveInteropTest.cs (System.IO.Compression → crypto, added by #122093). So the AOT assembly set is identical before and after the change, driver-gen.c content is byte-identical, CopyIfDifferent leaves the old timestamp, and the unchanged: false assertion for driver-gen.c fails.

Fix

NativeRebuildNewAssembly.cs now additionally references System.Text.RegularExpressions (Regex), which is not otherwise part of the app's closure (verified: it is absent from the actual failing build's AOT list, and no other source in WasmBasicTestApp uses it). The rebuild therefore genuinely adds a new AOT module, driver-gen.c is regenerated, and the assertion passes. A framework assembly was chosen (rather than a local ProjectReference) because it is simply never pulled in the first build when unused, making it reliably absent. The original crypto usage is kept as-is.

Fix 2 — stale published dotnet.native.wasm picked in the relink case

Problem

With Fix 1 in place, the AOT case passes, but the relink case (aot: False, invariant: False) then fails:

File sizes don't match for
obj/.../wasm/for-publish/dotnet.native.wasm (3066497)
publish/wwwroot/_framework/dotnet.native.r26owxu9r7.wasm (3066264)

This looked flaky (the Windows leg passed while Linux failed), but it is deterministic — it depends on the alphabetical order of two content-hash fingerprints.

Root cause

The test publishes twice into the samewwwroot/_framework:

  1. FirstNativeBuildAndRun publishes the baseline app → dotnet.native.<fpA>.wasm.
  2. Rebuild (now genuinely referencing a new assembly) relinks dotnet.native.wasm to a larger, differently-fingerprinted file → dotnet.native.<fpB>.wasm, copied into the same directory.

_PublishCopyStaticWebAssetsPreserveNewest never deletes the first publish's fingerprinted copy, so both files coexist. ProjectProviderBase.FindAndAssertDotnetFiles globbed dotnet.*, consumed both matches, and kept the alphabetically-last one — which could be the stale first-publish file — then compared it against the freshly relinked obj output, producing the size mismatch. This latent test-infra bug was previously masked because the test failed earlier (Fix 1) before the relink assertion ran.

Fix

When multiple fingerprinted variants of the same logical file are present, FindAndAssertDotnetFiles now keeps the newest one by last-write time. The rebuild always writes a newer timestamp (guaranteed by the existing 5s delay in NativeRebuildTestsBase.Rebuild), so the assertion reliably compares against the current build output.

Validation

All five ReferenceNewAssembly cases pass locally against a Mono browser-wasm Release build with workloads:

Wasm.Build.Tests Total: 5, Errors: 0, Failed: 0, Skipped: 0

Note

This PR description and change were generated with the assistance of GitHub Copilot.

…rated
The test replaced Program.cs to use System.Security.Cryptography (SHA256), expecting a new assembly to be added to the AOT set so driver-gen.c (the AOT modules table) would be regenerated. However WasmBasicTestApp already pulls System.Security.Cryptography into its closure via HttpTest.cs (HttpClient -> System.Net.Http -> crypto), so the AOT assembly set was identical before and after the change. driver-gen.c is written with CopyIfDifferent, so its timestamp was unchanged and the 'Expected changed file: driver-gen.c' assertion failed (deterministically, Release/aot=True).
Additionally reference System.Text.RegularExpressions, which is not otherwise part of the app closure, so the rebuild genuinely adds a new AOT module and driver-gen.c is regenerated. Fixesdotnet#130540.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts a WASM native rebuild test asset so that the “rebuild introduces a new referenced assembly” scenario actually changes the AOT-compiled assembly set, ensuring driver-gen.c is regenerated during the rebuild path.

Changes:

  • Add a System.Text.RegularExpressions usage (Regex.IsMatch) to the rebuild entrypoint so the rebuild reliably pulls in an additional framework assembly.
  • Add a clarifying comment explaining why the extra reference is needed for the test’s native-artifact change expectations.

@pavelsavara

Copy link
Copy Markdown
MemberAuthor

Regression attribution

The regression was introduced by #122093 ("Add Zip Archives password support", commit 0174483, merged 2026-07-09), which added a new dependency to System.IO.Compression:

<ProjectReferenceInclude="...System.Security.Cryptography\src\System.Security.Cryptography.csproj" />

WasmBasicTestApp uses ZipArchiveInteropTest.cs (System.IO.Compression, [JSExport]-rooted — it's in the app's AOT closure), so after that change the app now transitively pulls System.Security.Cryptography into its closure in both the first build and the rebuild. The ReferenceNewAssembly test replaced Program.cs to use SHA256 expecting that to add a new AOT module; with crypto already present, the AOT assembly set is identical before/after, driver-gen.c (written via CopyIfDifferent) keeps its timestamp, and the unchanged: false assertion fails.

Timeline confirms it: the Known Build Error first matched on 2026-07-11 (~1.5 days after #122093 merged on 07-09), as a single continuous failure period.

#122093 is a legitimate product change (zip encryption genuinely needs crypto), so the correct fix is on the test side — reference an assembly (System.Text.RegularExpressions) that is genuinely outside the app closure — rather than reverting it.

Note

This comment was generated with the assistance of GitHub Copilot.

…ale-file comparison
ReferenceNewAssemblyRebuildTest publishes twice into the same wwwroot. The rebuild relinks dotnet.native.wasm to a larger, differently-fingerprinted file, but the first publish's fingerprinted copy is not removed. FindAndAssertDotnetFiles globbed dotnet.* and kept the alphabetically-last match, which could be the stale file, causing an order-dependent 'File sizes don't match' failure. Keep the newest matching file (the current rebuild output) instead.
CopilotAI review requested due to automatic review settings July 14, 2026 10:44

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment threadsrc/mono/wasm/Wasm.Build.Tests/ProjectProviderBase.cs
@pavelsavarapavelsavara changed the title [wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c not regenerated[wasm] Fix ReferenceNewAssembly rebuild test: driver-gen.c regeneration and stale-native comparisonJul 14, 2026
@lewing
lewing merged commit 081d9a4 into dotnet:mainJul 14, 2026
43 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest.ReferenceNewAssembly failure: Expected changed file: driver-gen.c

4 participants

@pavelsavara@lewing@ilonatommy