Skip to content

Commit aaa24c3

Browse files
authored
Fixes a flake in reload shaders tests (flutter#184268)
fixes flutter#184265 This fixes an oddity related to mmap files. A delay had to be introduced in the test because of oddities with the filesystem. I tried a few tricks to get it to work without the delay but this is the only way I could get it to work. testing: has existing test, removes a flake I tested it manually locally: ``` for i in {1..30}; do echo "Running iteration: $i"; ./testing/run_tests.py --type=dart --dart-filter=shader_reload_test.dart --variant host_debug_unopt_arm64; done ``` ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [AI contribution guidelines]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent b2e6bfb commit aaa24c3

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

engine/src/flutter/testing/dart/vm_service/shader_reload_test.dart

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ void main() {
7676
final Uint8List sourceA = File(shaderSrcA).readAsBytesSync();
7777
final Uint8List sourceB = File(shaderSrcB).readAsBytesSync();
7878

79-
fileC.writeAsBytesSync(sourceA, flush: true);
79+
await _deleteAndWrite(fileC, sourceA);
8080

8181
try {
8282
final FragmentProgram program = await FragmentProgram.fromAsset(testAssetName);
8383
final FragmentShader shader = program.fragmentShader();
8484
final UniformFloatSlot slot = shader.getUniformFloat('iVec2Uniform');
8585
expect(slot.shaderIndex, 1);
8686

87-
fileC.writeAsBytesSync(sourceB, flush: true);
87+
await _deleteAndWrite(fileC, sourceB);
8888
await _performReload(testAssetName);
8989
expect(slot.shaderIndex, 5);
9090
} finally {
@@ -110,15 +110,15 @@ void main() {
110110
final Uint8List sourceA = File(shaderSrcA).readAsBytesSync();
111111
final Uint8List sourceB = File(shaderSrcB).readAsBytesSync();
112112

113-
fileC.writeAsBytesSync(sourceA, flush: true);
113+
await _deleteAndWrite(fileC, sourceA);
114114

115115
try {
116116
final FragmentProgram program = await FragmentProgram.fromAsset(testAssetName);
117117
final FragmentShader shader = program.fragmentShader();
118118
final UniformFloatSlot slot = shader.getUniformFloat('iMat2Uniform', 3);
119119
expect(slot.shaderIndex, 6);
120120

121-
fileC.writeAsBytesSync(sourceB, flush: true);
121+
await _deleteAndWrite(fileC, sourceB);
122122
await _performReload(testAssetName);
123123
expect(slot.shaderIndex, 7);
124124
// Make sure there is no crash here.
@@ -146,15 +146,15 @@ void main() {
146146
final Uint8List sourceA = File(shaderSrcA).readAsBytesSync();
147147
final Uint8List sourceB = File(shaderSrcB).readAsBytesSync();
148148

149-
fileC.writeAsBytesSync(sourceA, flush: true);
149+
await _deleteAndWrite(fileC, sourceA);
150150

151151
try {
152152
final FragmentProgram program = await FragmentProgram.fromAsset(testAssetName);
153153
final FragmentShader shader = program.fragmentShader();
154154
final UniformFloatSlot slotA = shader.getUniformFloat('iFloatUniform');
155155
slotA.set(1.0);
156156

157-
fileC.writeAsBytesSync(sourceB, flush: true);
157+
await _deleteAndWrite(fileC, sourceB);
158158
await _performReload(testAssetName);
159159

160160
final UniformFloatSlot slotB = shader.getUniformFloat('iFloatUniformRenamed');
@@ -184,15 +184,15 @@ void main() {
184184
final Uint8List sourceA = File(shaderSrcA).readAsBytesSync();
185185
final Uint8List sourceB = File(shaderSrcB).readAsBytesSync();
186186

187-
fileC.writeAsBytesSync(sourceA, flush: true);
187+
await _deleteAndWrite(fileC, sourceA);
188188

189189
try {
190190
final FragmentProgram program = await FragmentProgram.fromAsset(testAssetName);
191191
final FragmentShader shader = program.fragmentShader();
192192
final ImageSamplerSlot slot = shader.getImageSampler('tex_a');
193193
expect(slot.shaderIndex, 0);
194194

195-
fileC.writeAsBytesSync(sourceB, flush: true);
195+
await _deleteAndWrite(fileC, sourceB);
196196
await _performReload(testAssetName);
197197
expect(slot.shaderIndex, 1);
198198
} finally {
@@ -204,3 +204,18 @@ void main() {
204204
}
205205

206206
void _use(Shader shader) {}
207+
208+
/// Delete the file first, if it exists, to ensure the engine doesn't attempt
209+
/// to read a memory-mapped file that is actively being truncated and written to.
210+
Future<void> _deleteAndWrite(File file, Uint8List bytes) async {
211+
if (file.existsSync()) {
212+
file.deleteSync();
213+
}
214+
file.writeAsBytesSync(bytes, flush: true);
215+
// Allow time for the macOS file system metadata caching to settle.
216+
// Otherwise, the engine's subsequent `fstat` may read a `0` st_size
217+
// or `openat` may fail entirely due to APFS asynchronous directory updates.
218+
//
219+
// renameSync() was tried but it was not sufficient to fix the issue.
220+
await Future<void>.delayed(const Duration(milliseconds: 100));
221+
}

0 commit comments

Comments
 (0)